认识kmp前 先了解下BF(暴力穷举)
查找子串在主串中首次出现的位置,若未出现输出0:
#include <bits/stdc++.h>
using namespace std;
int main(){
char a[1000],b[1000];
gets(a); //主串
gets(b);
int i=0,j=0;
while(a[i]!='\0' && b[j]!='\0'){
if(a[i]==b[j]){
j++;
i++;
}
else{
i=i-j+1; //i=1 2 3 ....
j=0;
}
}
if(b[j]=='\0')
cout<<i-j+1;
else
cout<<"0";
return 0;
}
然而,这种方法效率极低,需要像乌龟一样慢慢往后爬。就此引出KMP算法。
了解kmp前先补充的知识:
前缀 后缀 前后缀公共最大长
了解之后,引入next数组,将从开头到此位置的子串的部分串(又或者叫子串的子串)的前后缀公共最大长存入。
new数组是next数组的数值-1
关于next数组的值,是需要自己求出来的。具体的求法后边再说。
现将A串(主串)和B串匹配
到第6位的时候(下标为5)匹配失败,查找前边匹配成功的长度为5的子串的最大公共长。
然后主串依旧从第6位开始匹配,子串从第(最大公共长+1)的位置开始匹配。
譬如第一轮匹配失败后,abaab的最大公共长是2,最大公共长+1的位置就是3,就从a[5]是否等于b[2]往后开始判断,进行新一轮的匹配,依次循环。
现在要解答上边的疑问,如何求next数组(或者new数组):
为了说明通解,不从第二位开始,就假设next[0]~next[9]均已经求出来,则要判断b[10]和b[10]前的最长字符串“abaabbabaa”最大前缀的后一位是否相等。
而现在如何找“abaabbabaa”最大前缀的后一位?答案即下标为next[9]的索引值。(next[9]对应了公共最大长的值,也表示着最大前缀后一位的索引)
若相等,则next[10]=next[9]+1。若不相等,譬如最后b[10]=a,此时b[10]前的最长字符串“abaabbabaa”最大前缀是(或者叫最大后缀,二者相等)“abaa”,即问题转换成了求“abaa”后加了“a”,也就是新串“abaaa”的最大公共长,