对KMP算法的理解

为什么KMP算法与主串无关,只与模式串有关:

因为模式串是与主串匹配的,模式串才是关键,主串要么就没有与模式串匹配的字串,要么就必然有字串与模式串匹配,所以说最终还是回到了模式串。而实际上KMP算法的关键就是模式窜找自己的字串,然后用next数组记录下来,用next数组来控制匹配时模式串滑动的长度。

 

怎样求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[1]=0是固定的。

next[2]=1,则模式串长度为2=“ab”,这时ab的最大字串长度为1,无法在字串中找到与之匹配的字串,故next[2]=1,表示下次若与主串匹配时若在2位置失配,就得回溯到1位置重新匹配。

以此类推,则当到next[7]时,next[7]=3,则模式串长度为5=“abcaaba”,这时abcaaba的最大字串长度为4=“abcaab”,这时,前缀ab=后缀ab,个数为2,所以next[7]=2+1=3。表示下次若与主串匹配时若在7位置失配,就得回溯到3位置重新匹配。为什么从3开始匹配呢?因为我们在前面就已经比较过模式串的字串了,知道1、2位置与5、6位置字母相同,所以就没有必要再比较一次了。所以便从第3个位置与失配的位置开始比较。

 

求next数组的代码:

Void get_next(char t[],int Next[]){
Next[1]=0;
int j=0;//前缀
int i=1;//后缀
while(i<t[0]){
if(j==0||t[j]==t[i]){
//j==0则表示在第一个位置就失配了
i++;j++;
Next[i]=j;
}
else{
 j=next[j];
}
}
}

KMP算法代码:

int KMP(int pos,int Next[],char s[],char t[]){
//将主串,模式串,next数组,还有pos(从主串第几个位置开始模式匹配)传过来
int i=pos;j=1;
while(i<=s[0]&&j<=t[0]){
if(j==0||s[i]==t[j]){
//j==0则表示在第一个位置就失配了,则这时主串与模式串就都需要后移一个位置再进行匹配。
 i++;
 j++;
}
else{
 j=Next[j];//右滑
}
}
if(j>t[0]){
Return i-t[0];//返回匹配成功的初始位置
}
else{
return 0;//匹配失败
}
}​

其实KMP算法实际上就是对BF算法最耗时的回溯进行了改进,让匹配效率大大提高了。那下面也附上BF算法的代码吧。

int BF(char s[],char t[]){
//将主串,模式串传过来
int i=1;j=1;
while(i<=s[0]&&j<=t[0]){
if([i]==t[j]){
 i++;
 j++;
}
else{//回溯
i=i-j+2;//返回到主串中第一个没有匹配过的位置
j=1;//返回到模式串中第一个位置与主串重新匹配
}
}
if(j>t[0]){
return i-t[0];//返回匹配成功的初始位置
}
else{
return 0;//匹配失败
}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值