串的模式匹配算法
作者:互联网
暴力匹配算法
int Index(SString S,SString T,int pos){
//返回子串T在主串S中第pos个字符之后的的位置,若不存在,则函数值为0.
//其中,T非空,1<=pos<=StrLength(S).
int i=pos,j=0;
while(i<=S[0]&&j<=T[0]){
if(S[i]==T[j]){
i++;j++;
}else{
i=i-j+2;
j=1;
}
}
if(j>T[0])return i-T[0];
else return 0;
}
在上述算法中,字符串采用定长顺序存储结构,具体如下:
算法的基本思想是:从主串S的第pos个字符起和模式的第一个字符比较,若相等,则继续逐个比较之后的字符;否则从主串的下一个字符起再重新和模式的字符比较。该算法的时间复杂度为O(mn),m和n分别是两个字符串的长度。
注:上述代码更多的是阐释暴力匹配算法的思想,具体代码请根据所采用的编程语言以及字符串存储的数据结构来决定。
KMP算法
改进在于:每当一趟匹配过程中出现字符比较不等时,不需要完全回溯指针,而是利用已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远的一段距离后,继续进行比较。
假设主串‘s1 s2 …sn’,模式串为‘p1,p2…pm’,从上例的分析可知,为了实现改进算法,需要解决下述问题:当匹配过程中产生“失配”(即si!=pj)时,模式串“向右滑动”可行的距离多远,换句话说,当主串中第i个字符与模式中第j个字符“失配“时,主串第i个字符应该与模式串中哪个字符再进行比较?
int Index_KMP(SString S,SString T,int pos){
//利用模式串T的next函数求T在主串S中第pos个字符之后的位置
//其中,T非空,1<=pos<=StrLength(S).
int i=pos;
int 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数组索引是从1开始的
那么如何去求next数组呢?
void get_next(SString T,int next[]){
//求模式串T的next函数值并存入数组next。
int i=1;
next[1]=0;
int j=0;
while(i<T[0]){
if(j==0||T[i]==T[j]){++i;++j;next[i]=j;}
else j=next[j];
}
}
其实通俗来讲就是模式串T与自身进行匹配。
针对某些特殊情况
void get_nextval(SString T,int nextval[]){
//求模式串T的next函数值并存入数组next。
int i=1;
nextval[1]=0;
int j=0;
while(i<T[0]){
if(j==0||T[i]==T[j]){
++i;++j;
if(T[i]!=T[j])nextval[i]=j;
else nextval[i]=nextval[j];
}
else j=next[j];
}
}
注:本篇所有代码仅仅是为了表达思想,具体情况具体定!!!
标签:SString,nextval,int,else,++,算法,next,模式匹配 来源: https://blog.csdn.net/weixin_44394238/article/details/114118010