KMP是在传统的简单模式匹配基础上进化来的,通过向右尽量滑动远一点,除去冗余的滑动操作提高效率。更加详细的讲解拜访这位大侠:http://kb.cnblogs.com/page/176818/
编码实现:
#include <iostream> #include<cstdio> #include<cstring> using namespace std; char str[100]; int next[100],len; void getnext(){ int i=0,j=-1; next[0]=-1; while(i<len){ if(j==-1||str[i]==str[j]){ i++; j++; next[i]=j; } else j=next[j]; } } int main() { //freopen("cin.txt","r",stdin); while(cin>>str){ len=strlen(str); getnext(); printf("str&&next: \n"); for(int i=0;i<len;i++){ cout<<i<<": "<<str[i]<<" "<<next[i]<<endl; } } return 0; }
两个输入输出例子:
abaabcac
str&&next:
0: a -17: c 1
abcdabd
str&&next:
0: a -1
1: b 0
2: c 0
3: d 0
4: a 0
5: b 1
6: d 2
next[]保存了str的部分匹配值(前缀和后缀最长的共有元素长度),对于abcdabd字符串的部分匹配值是{0,0,0,0,1,2,0},这表示原字符串前缀abcd没有前后缀公有元素,继续往后看abcda,a是公有元素,所以匹配值是1,abcdab的公有元素有两个,所以匹配值是2……
hdu 1711
2 13 5 1 2 1 2 3 1 2 3 1 3 2 1 2 1 2 3 1 3 13 5 1 2 1 2 3 1 2 3 1 3 2 1 2 1 2 3 2 1
6 -1
#include <iostream> #include<cstdio> #include<cstring> using namespace std; const int maxm=1e4+5,maxn=1e6+5; int n,m; //m is shorter int a[maxn],b[maxm],bnext[maxm]; void getbnext(){ int i=0,j=-1; bnext[0]=-1; while(i<m){ if(j==-1||b[i]==b[j]){ i++; j++; bnext[i]=j; } else j=bnext[j]; } } int KMP(){ int i=0,j=0; while(i<n&&j<m){ if(j==-1||a[i]==b[j]){ i++; j++; } else j=bnext[j]; } if(j>=m)return i+1-j; else return -1; } int main() { //freopen("cin.txt","r",stdin); int t,i,j; cin>>t; while(t--){ scanf("%d%d",&n,&m); for(i=0;i<n;i++)scanf("%d",&a[i]); for(i=0;i<m;i++)scanf("%d",&b[i]); memset(bnext,0,sizeof(bnext)); getbnext(); printf("%d\n",KMP()); } return 0; }