关于KMP算法的一个问题
下面是KMP算法中计算失配的函数,其中有几个不明白的地方(用红色标出)
void fail(char *pat)
{
int n=strlen(pat);
int i,j;
failure[0]=-1;
for(j=1;j<n;j++){
i=failure[j-1];
while((pat[j] != pat[i+1]) && (i >= 0))
i=failure[i];
if(pat[j] == pat[i+1])
failure[j]=i+1;
else
failure[j]=-1;
}/*end of for*/
}/*end of fail*/
while循环有什么用,还有这个失配函数是根据什么数学原理写出来的
[解决办法]
KMP的思想是这样的假如有串
A = 'cabcaaabc'
若我有串abcab需要在模式串中查找,则对串abcab对其计算失效函数
a b c a b
0 0 0 1 2
现在来解释一下下面的数字,执行while循环的时候,每次查看当前字符指针与游标所指的字符是否相同,游标初始为第一个位置的字符即a,当前指针初始为下一字符即b,这里还需要另一个计数器count初始为0
查看a与b不相等,将f(x)置为count,将当前字符指针向前移动(指向了c),游标不动
同上一步骤,a与c比较不等,继续向前移动
到当前指针指向a的时候发现游标与当前所指相同了,将count自增然后赋给失效函数f(x),游标和当前字符都向前移动
现在来解释这样做有什么用
在A中查找abcab这个串时,分别有两个指针指向原串(p1)和模式串(p2),它们这样匹配
c a b c a a a b c p1 = 0
a b c a b p2 = 0
发现两个字符不同,根据计算出的失效函数的值来确定匹配失败后abcab这个串的下一位置,将模式串的指针向前移动,可能不太清楚,下面通过具体形式来说明
第一次未匹配
c a b c a a a b c p1 = 0
a b c a b p2 = 0
第二次 匹配成功
c a b c a a a b c p1 = 1
a b c a b p2 = 0
第三次 匹配成功
c a b c a a a b c p1 = 2
a b c a b p2 = 1
第四次 匹配成功
c a b c a a a b c p1 = 3
a b c a b p2 = 2
第五次 匹配成功
c a b c a a a b c p1 = 4
a b c a b p2 = 3
第六次未匹配成功 f(4)是2,于是将p2赋值为2,发现p2还是指向了b,略去了重新匹配前面的一个a的工作
c a b c a a a b c p1 = 5
a b c a b p2 = 4
第七次。。。。
直到结束,或找到或未找到,
这里失效函数的具体含义就是模式中相同串偏移
a b c a b
其中有ab两个字串是相同的,后面的a b的失效函数分别指向了与其相同的字串的偏移
有一个很经典的例子:
有一个字符串是有很多相同的字串重复叠加而组成的,计算该字符串是由哪个最小字串重复组成的,并计算其出现的个数
比如ababab是由ab子串组成的,共有3个
abcab是由abcab子串组成的,共有1个
这个题是失效函数的最好例子