一. 简单模式匹配算法
对某一个串中某子串定位的操作称为串的模式匹配。(注意:求出的是字串在主串中的起始位置)
简单模式匹配算法的思想是:主串与模式串(待定位的串)从第一个位置开始进行比较,如果相等则比较下一字符,如果不相等则使模式串从第一个字符和主串的第二个字符进行比较,以此类推。
int Str_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; //当前字符匹配后移
++j;
}
else{ //当前不匹配k指针后移,模式串在k处从新比较
j=1;
i = ++k;
}
}
if(j>substr.length)
return k; //成功返回主串中相匹配的位置
else
return 0;
}
可以看出来,这种算法是很笨的一种算法,最坏的情况下时间复杂度为O(m*n)。
二. KMP算法
上面的简单算法可以看出,当模式串前些元素已经比较完成的情况下匹配失败进行下一轮比较时,由于比较过的部分有可能是ABxxxAB型的,就是说我们可以利用已经部分匹配这个有效信息,保持i指针不回溯,通过修改j指针,让模式串尽量地移动到有效的位置,对于上面的例子,我们就是要跳过AB部分直接比较x的部分,原因就是AB部分已经在当前比较部分之前的尾部比较过了,因为我们可以直接看出需要跳到哪里,但是程序怎样知道应该跳到哪里呢?我们事先对模式串定义了一个NEXT数组,当主串与模式串发生不匹配的情况下,直接将模式串跳到NEXT数组对应的位置即可,从而使主串不需要回溯。
int KMP(Str str, Str Substr, int *next){
//对 substr进行KMP匹配
int i=1,j=1;
while(i<=str.length && j<=Substr.length){
if(j==0 || str.ch[i] == Substr.ch[j]){
++i;
++j;
}
else{
j = next[j];
}
}
if(j>Substr.length)
return i-Substr.length;
else
return 0;
}
那么NEXT数组应该怎么求呢?其实和KMP算法差不多。
void getnext(Str str, int *next){
//求模式串str的next数组
int i=1,j=0;
next[0] = str.length;
next[1] = 0;
while(i<str.length+1){
if(j==0 || str.ch[i] == str.ch[j]){
++i;
++j;
next[i] = j;
}
else
j = next[j];
}
}