您的位置:首页 > 其它

KMP字符串匹配(1)

2011-11-17 14:15 225 查看
近日看到一面试题写一个函数从字符串s中查找出子串t,并将t从s中删除。

这是考查KMP匹配算法,以前读书时学KMP总是一知半解,考完试基本都还给老师了,

唯一的印象就是KMP实现了匹配字符串指针不回溯,极大的提高了效率,

最近代码写的少拿此题练练手。

考虑当第k个字符失配的时候,sm+k+1≠tk+1时,有如下关系

sm+1sm+2…sm+k
= t1t2…tk
下一次再比较时,指针不回溯,应该比较sm+k+1和t的哪个字符呢?

假设应该和ti比较,那么有如下关系

t1t2…ti-1
= sm+k-i+2sm+k-i+3…sm+k (i-1<k)

t1t2…ti-1
= tk-i+2tk-i+3…tk (i-1<k),这是字符串t自身的匹配关系,

当然这样的i可能不止一个,next[i]就是所有这样i里面的最大值,

i越大也意味着满足t1t2…ti-1
= tk-i+2tk-i+3…tk关系的k-i+2越小,

因此下一个需要比较的就是满足上述条件i的最大值,失配后t往右移动的距离最小,

字符串t第i个字符失配后sm+k+1应该和t的next[i]个字符继续比较。

举个具体例子s=“ababababababc“, t=“abababc“当s[6]=a与t[6]=c失配时,

s[6]应该和t[4]=a继续比较,再失配和t[2]=a比较,而不能先和t[2]=a比较,

这样如果原始字符串s=“ababababc“结果就不对了。

有了上述推理,不难写出匹配代码:

i,j分别指向s,t中某个字符,一直匹配,直到某字符失配后,j=next[j]继续比较,

如果next[j]=-1,表示第一个字符就不匹配,此时++i, 比较s的下一个字符,

tlen-j是字符串中待比较字符个数,循环退出条件是s中剩余字符小于t中待比较字符数。

while(i<=slen-tlen+j){

if(s[i] == t[j]){

++i;

++j;

//find match string, erase it

if ( j == tlen){

strcpy(s+i-tlen, s+i);

slen -= tlen;

i -= tlen;

j = 0;

}

}

else{

if ( (j = next[j]) == -1 ){

++i;

j = 0;

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: