目录
KMP
得到NEXT数组
理论
我们先来看一个例子:
abcaabc 将这个当成模式串,当我们用这个模式串去匹配文本串的时候,我们首先有一种很暴力的做法: 就是每次匹配失败的时候重新开始匹配,但这样有很多重复。 那么我们是不是可以想一种办法,减少这种重复呢。 先看一个表格j | i | 模式串 | next |
---|---|---|---|
-1 | 0 | next[0]=-1 | |
0 | 1 | a | next[1]=0 |
-1 | 1 | ||
0 | 2 | ab | next[2]=0 |
-1 | 2 | ||
0 | 3 | abc | next[3]=0 |
1 | 4 | abca | next[4]=1 |
0 | 4 | ||
1 | 5 | abcaa | next[5]=1 |
2 | 6 | abcaab | next[6]=2 |
3 | 7 | abcaabc | next[7]=3 |
通过上面这个表格我们是不是有所发现:
1、next[i]=j (当j!=-1&&i!=0时满足) 2、i 就表示模式串的长度 (当然你要用模式串长度-1也行,详见下面的表格,代码就不贴了,留给你自己发挥了) 3、next[0]=-1 (这是为了方便回溯,方便创建next数组)j | i | 模式串 | next |
---|---|---|---|
-1 | 0 | a | next[0]=-1 |
0 | 1 | ab | next[1]=0 |
-1 | 1 | ||
0 | 2 | abc | next[2]=0 |
-1 | 2 | ||
0 | 3 | abca | next[3]=0 |
1 | 4 | abcaa | next[4]=1 |
0 | 4 | ||
1 | 5 | abcaab | next[5]=1 |
2 | 6 | abcaabc | next[6]=2 |
代码
void getNEXT() { int i = 0, j = NEXT[0] =-1; while (i
在文本串中找到第一个模式串的位置
int FirstKmp() { int i = 0, j = 0; while (i < a.size()) { if (j == -1 || a[i] == Find[j]) { i++, j++; if (j == Find.size()) { return i - j; } } else j = NEXT[j]; } return -1;}//在a中找到第一个Find的位置
查找文本串中有多少模式串
可以重叠的
int ManyKmp() { int i = 0, j = 0,ans=0; while (i < a.size()) { if (j == -1 || a[i] == Find[j]) { i++, j++; if (j == Find.size()) { ans++; j = NEXT[j]; } } else j = NEXT[j]; } return ans;} //在a中找几个可以重叠的Find
不可以重叠的
int ManyKMP() { int i = 0, j = 0, ans = 0; while (i < a.size()) { if (j == -1 || a[i] == Find[j]) { i++, j++; if (j == Find.size()) { ans++; j = 0; } } else j = NEXT[j]; } return ans;}//在a中找几个不可以重叠的Find
其他小结
如果一个字符串满足 len%(len-next[len])==0,则这个字符串是一个周期串(存在最小循环节),循环次数为 len / ( len-next[len] )
如果 len%(len-next[len])!=0,这个字符串也存在循环节,但是最后一个循环节不完整