KMP算法
KMP算法是一种字符串模式匹配算法。
什么是字符串的模式匹配?
给定两个串S=“s1s2s3 …sm”和T=“t1t2t3 …tn”,在主串S中寻找子串T的过程叫做模式匹配,T称为模式。
暴力匹配(朴素模式匹配BF)
规定i是主串S的下标,j是模式T的下标。现在假设现在主串S匹配到 i 位置,模式串T匹配到 j 位置。
如果当前字符匹配成功(即S[i] = T[j]),则i++,j++,继续匹配下一个字符;
如果失配(即S[i] != T[j]),令i = i - (j - 1),j = 0。相当于每次匹配失败时,i 回溯到本次失配起始字符的下一个字符,j 回溯到0。
int BF(char S[],char T[]) { int i=0,j=0; while(S[i]!='\0'&&T[j]!='\0') { if(S[i]==T[j]) { i++; j++; } else { i=i-j+1; j=0; } } if(T[j]=='\0') return (i-j); //主串中存在该模式返回下标号 else return -1; //主串中不存在该模式 }
1. 背景KMP算法一种改进的模式匹配算法,是D.E.Knuth、V.R.Pratt、J.H.Morris于1977年联合发表,KMP算法又称克努特-莫里斯-普拉特操作。它的改进在于:每当从某个起始位置开始一趟比较后,在匹配过程中出现失配,不回溯i,而是利用已经得到的部分匹配结果,将一种假想的位置定位“指针”在模式上向右滑动尽可能远的一段距离到某个位置后,继续按规则进行下一次的比较。
前缀与后缀
前缀:含有首字符不含尾字符的所有子串。
后缀:含有尾字符不含首字符的所有子串。
最长相等前后缀的长度next数组
现在有串P=abaabca,各个子串的最大相等前后缀长度如下表所示:
这样,最长相等前后缀最长长度就会和串P的每个字符产生一种对应关系:
这个表的含义是在当前字符作为最后一个字符时,当前子串所拥有的公共前后缀最长长度。例如当c作为最后一个字符时,当前子串abaabc并没有公共前后缀。
接下来我们就用这个表来引出next数组,next 数组的值是公共前后缀最长长度。我们称next数组中的值为失效函数值。
#include#include using namespace std; void getnext(int *next,string &s) { int i,j; next[0]=0; j=0; for (int i=1;i 0&&s[j]!=s[i]) { j=next[j-1]; } if (s[j]==s[i]) j++; next[i]=j; } } int Kmp(string s,string t) { int *next; next= new int [s.size()+1]; getnext(next,s); int i=0,j=0; for (i=0;i 0&&s[j]!=t[i]) { j=next[j-1]; } if (s[j]==t[i]){ j++; } if (j==s.size()) { return i-j+1; } } return -1; } int main() { string s,t; cin>>t; cin>>s; cout<