①简单的模式匹配
int index(Str str,Str Substr) { int i=1,j=1,k=i; while(i<=str.length&&j<=Substr.length) { if(str.ch[i]==Substr.ch[j]) { i++;//i指向主串中的位置 j++;//j指向模式串中的位置 } else { j=1; i=++k; } } if(j>Substr.length) return k;//主串str.ch中的子串与模式串Substr.ch匹配后,j还是会+1,所以是j>Substr.length else return 0; }
②KMP算法
(1.1) 获取next数组
<1> 在这里next数组下标从0开始!
<2> next[i]就是当模式串(子串)第i位不匹配时即将要返回的模式串下标位置。
void getnext(Str Substr,int next[]) { int i=0,j=-1;//i指向串尾,j指向串头 next[0]=-1; while(i<Substr.length-1) { if(j==-1||Substr.ch[i]==Substr.ch[j]) next[++i]=++j; else j=next[j]; } }
手算next数组的诀窍:
⑴ 首先,next[0]肯定是-1;
⑵ 其次,next[1]肯定是0 ;
⑶ 分析next[n]的情况:前n个字符从首尾开始组成的最大相同子串的长度,如果找到,那么next[n]=该长度,否则为0。
eg:有模式串abaabaca,求next[6]的值。
已知在模式串中下标为6的元素为c,将c前面的6个字符(下标为0~5)从头尾各取5个字符进行比较,如果不相同,则再从首尾各取4个字符进行比较,以此类推,情况如下:
5个字符的情况:abaab≠baaba
4个字符的情况:abaa≠aaba
3个字符的情况:aba=aba,所以最终得出next[6]=3;
如果一直比较到最后一个字符都不相同,那么该next值为0;
ps:如果下标从1开始,则将next数组中的所有值+1,下标均前移1位。
(1.2) next数组的改进——nextval数组
void getnextval(Str Substr,int nextval[]) { int i=0,j=-1; nextval[0]=-1; while(i<Substr.length-1) { if(j==-1||Substr.ch[i]==Substr.ch[j]) { i++; j++; if(Substr.ch[i]!=Substr.ch[j]) nextval[i]=j; else nextval[i]=nextval[j]; } else j=nextval[j]; } }
(2) kmp匹配
int kmp(Str str,Str Substr,int next[]) { int i=0,j=0; while(i<str.length&&j<Substr.length) { if(j==-1||str.ch[i]==Substr.ch[j]) { i++; j++; } else j=next[j]; } if(j==Substr.length) return i-Substr.length; else return -1; }