KMP算法及求next函数值
今天复习到了串的模式匹配,有两种算法,一种简单的,还有一种改良后的,称为KMP算法。这篇说我对KMP算法的理解。
KMP
s串:主串;t串:子串
先说一下为什么要改良,简单的模式匹配效率低速度慢,而造成这种局面的根本就是一遍又一遍的返回,匹配失败后,s串回到下一个字符,t串回到第一个字符,这是不必要的,这就使效率变低。
如果在某趟匹配过程中,在Si和tj匹配失败后(即 t1t1…tj-1 = Si-j+1Si-k+2…Si-1 tj前所有字符与Si前所有字符匹配成功),i不返回到s串下一个字符,而是向右滑,存在tk前所有字符与Si前所有字符匹配成功,即 t1t2…tk-1 = Si-k+1Si-k+2…Si-1(原谅我不会打下标),k一定比j小,因为j后的字符还没有匹配到,所以tj的前k个字符与Sj的前k个字符匹配,即tj-k+1tj-k+2…tj-1 = Si-k+1Si-k+2…Si-1,以上可知,t1t2…tk-1=tj-k+1tj-k+2…tj-1
所以只要当匹配失败时,找出k值,就可以使tk对准Si继续匹配。
假设已有next函数情况下KMP代码:
int KMP(char s[],char t[],int next[])
{
int i=pos,j=1;
while(i<=s[0]%%j<=t[0])//没遇到结束符
{
if(j==0||s[i]==t[j])
i++;j++;
else j=next[j];//右滑
}
if(j>t[0]) return (i-t[0]);
else return 0;
}
next
我们把要求的k值表示为next(j),next值取决于子串本身。next(1)=0是一定的。
设next(j)=k,即t1t2…tk-1=tj-k+1tj-k+2…tj-1
那么next(j+1)等于什么呢?
如果tk=tj,即t1t2…tk=tj-k+1tj-k+2…tj也就是 next(j+1)=k+1=next(j)+1
如果tk!=tj的话,可把现在tk!=tj当做模式匹配问题,现在tk与tj不匹配,那么应该找到k’可以继续匹配,即next(k)=k’,tk’=tj;则t1t2…tk’=tj-k’+1tj-k’+2…tj所以next(j+1)=k’+1=next(k)+1
如果tk’!=tj一直找下去k一直减小直至1,那么next(k)=0故next(j+1)=next(k)+1=1
代码如下:
void getnext(char t[],int next[])
{
int j=1,k=0;
next[1]=0;
while(j<t[0])//未遇到结束符
{
if(k==0||t[j]==t[k])
j++;k++;next[j]=k;
else k=next[k];
}
}
下面举一个例子
主串 | aabcbabcaabcaababc |
---|---|
子串 | abcaababc |
next
j | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|
子串 | a | b | c | a | a | b | a | b | c |
next(j) | 0 | 1 | 1 | 1 | 2 | 2 | 3 | 2 | 3 |
经以上代码测试正确,想自己测试一遍可进行测试,应该是没有问题的,如有问题请评论告诉我然后我修改哦
利用next函数进行匹配过程
第一趟:
a | a | b | c | b | a | b | c | a | a | b | c | a | a | b | a | b | c |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
a | b- | c | a | a | b | a | b | c |
b-位置失败,i=2,j=2,next(2)=1,故j=1,t1与S2比较
第二趟:
a | a | b | c | b | a | b | c | a | a | b | c | a | a | b | a | b | c |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
a | b | c | a- | a | b | a | b | c |
a-位置失败,i=5,j=4,next(4)=1,故j=1,t1与S5比较
第三趟:
a | a | b | c | b | a | b | c | a | a | b | c | a | a | b | a | b | c |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
a | b | c | a | a | b | a | b | c |
j++;i++;
第四趟:
a | a | b | c | b | a | b | c | a | a | b | c | a | a | b | a | b | c |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
a | b | c | a | a | b | a- | b | c |
a-位置失败,i=12,j=7,next(7)=3,故j=3,t3与S12匹配
a | a | b | c | b | a | b | c | a | a | b | c | a | a | b | a | b | c |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
a | b | c | a | a | b | a | b | c |
匹配成功
以上就是所有理解啦,我是参考课本和查找资料,自己理解并了解的,希望有什么不足请指出。bye