您的位置:首页 > 其它

暴力匹配和KMP算法模板

2016-08-12 19:58 211 查看
问题描述:

给出一个文本串S和一个模式串P,判断P是否在S中出现,若出现返回模式串中的位置。

暴力匹配算法思想

假设当前文本串遍历到i,模式串遍历到j:



1.若s[i]==p[j]则文本串和模式串继续匹配

               ++i;

               ++j;

2.若s[i]!=p[j]则文本串和模式串进行回溯后再匹配

              j=0;//模式串回到开头

              i=i-(j-1)=i-j+1;

3.经过若干次1,2过程的匹配知道文本串或模式串遍历完,则判断j?plen i-j:-1;

代码如下:

int ViolentMatch(char *s,char *p){

int slen=strlen(s);

int plen=strlen(p);

int i=0;

int j=0;

while(i<slen&&j<plen){

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

++i;

++j;

}

else{

j=0;

i=i-j+1;

}

}

if(j==plen) return i-j;

return -1;

}


2.KMP匹配算法思想

(1)整体过程

假设当前文本串遍历到i,模式串遍历到j,



1、若j==-1或s[i]==s[j],则文本串和模式串继续向后匹配

                ++i;

                ++j;

2.若j!=-1且s[i]!=s[j],则文本串不向前回溯即i不变,但模式串j向前回溯到next[j]的位置。

                j=next[j];

3.经过若干次1,2过程的匹配知道文本串或模式串遍历完,则判断j?plen i-j:-1;

int KmpSearch(char *s,char *p){

int slen=strlen(s);

int plen=strlen(p);

int i=0;

int j=0;

while(i<slen&&j<plen){

if(j==-1&&s[i]==p[j]){

++i;

++j;

}

else{

j=next[j];

}

}

if(j==plen) return i-j;

return -1;

}

(2)next数组计算过程

假设当前存在p0p1...pk-1=pj-kpj-k+1...pj-1

1.若当前存在p[k]==p[j],则next[j+1] =next[j]+1;

2.若当前p[k]!=p[j]则k向前回溯k=next[k];

代码如下:

void GetNext(char *p,int next[]){

int k=-1;

int j=0;

next[i]=0;

int plen=strlen(p);

while(j<plen-1){

if(j==-1||p[k]==p[j]){

++k;

++j;

next[j]=k;

}

else{

k=next[k];

}

}

}

(3).优化Next数组的计算过程

主要原因是:

如S:abacd   P:abab 当s[3]和P[3]匹配失败时回溯到s[3]和p[1]匹配此时还是失败的从而影响了匹配效率,此时应该继续向前回溯,优化过程则是在计算next时递归向前回溯。

void GetNext(char *p,int next[]){

int k=-1;

int j=0;

next[i]=0;

int plen=strlen(p);

while(j<plen-1){

if(j==-1||p[k]==p[j]){

++k;

++j;

if(p[k]!=p[j]){

next[j]=k;

}

else{

next[j]=next[k];//优化过程

}

}

else{

k=next[k];

}

}
}


总体来看,KMP算法的时间复杂度O(m+n)空间复杂度O(1)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  基础算法