KMP
KMP算法,刚开始看会有些难理解,这个其实多看几遍就好了,有关KMP的介绍也挺多的,在这里就不重复了,点击这里
这里扩展KMP(Z函数),点击这里
列举几道模板题:
HDOJ- 1711 Number Sequence(经典模板题)
#include<map> #include<set> #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<string> #include<cstdlib> #include<vector> #include<queue> #include<cmath> #include<stack> using namespace std; #define ms(x,n) memset(x,n, sizeof(x)); typedef long long LL; const int inf = 1<<30; const LL maxn = 1e6+10; int s1[maxn],s2[maxn],n,m; int nex[maxn]; void getNext(){ //前缀函数(滑步函数 int i=1 ,j=0; while(i < m){ if(j==0 || s2[i] == s2[j]){ //(全部不相等从新匹配 || 相等继续下次匹配 i++, j++; if(s2[i]!= s2[j]) nex[i] = j; else nex[i] = nex[j]; } else j = nex[j]; //子串移动到第nextval[j]个字符和主串相应字符比较 } } int kmp(){ getNext(); int i=1, j=1 ; while(i <=n && j<=m ){ if(s1[i] == s2[j] || j==0) i++,j++; else j = nex[j]; } if(j > m) return i-m; else return -1; } int main(){ int T; scanf("%d",&T); while(T--){ ms(s1, 0); ms(s2,0); ms(nex,0); scanf("%d%d",&n,&m); for(int i=1 ;i<=n ;i++) scanf("%d",&s1[i]); for(int j=1 ;j<=m ;j++) scanf("%d",&s2[j]); printf("%d\n",kmp()); } return 0; }
HDOJ-1686 Oulipo(经典模板题)
#include<cstdio> #include<cstring> char s1[1000010],s2[10010]; int next[10010] = {-1}; void getNext(char p[],int len){ int i,j=-1; for(i=1 ;i<len; i++){ while(j!=-1 && p[i]!=p[j+1]) j= next[j]; if(p[i] == p[j+1]) j++; next[i] = j; } } int kmp(char t[],char p[], int len1, int len2){ int i,j=-1; int count = 0; getNext(p,len2); for(i=0 ;i<len1 ;i++){ while(j!=-1 && t[i] != p[j+1]){ j=next[j]; } if(t[i] == p[j+1]) j++; if(j == len2-1) count++; } return count; } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%s%s",s2,s1); printf("%d\n",kmp(s1,s2,strlen(s1), strlen(s2))); } return 0; }
#include<iostream> #include<string> #include<cstdio> using namespace std; #define Max 1000005 int nex[Max]; int sum; void GetNext(string t){ int i = 0; int j=-1; while(i < (int)t.size()){ if(j == -1 || t[i] == t[j]){ i++; j++; nex[i] = j; } else j = nex[j]; } } void Kmp(string s1,string s2){ GetNext(s2); int i=0 ,j=0; int slen = (int)s1.size(); int tlen = (int)s2.size(); while(i < slen && j < tlen){ if(j == -1|| s1[i] == s2[j]){ if(j == tlen-1){ sum++; i++; j=0; } else { i++; j++; } } else j = nex[j]; } } int main(){ string s1; while(cin >> s1){ if(s1 == "#") break; string s2; cin >> s2; char ch = getchar(); sum =0; nex[0] =-1; Kmp(s1,s2); printf("%d\n",sum); } return 0; }
#include<cstdio> #include<cstring> using namespace std; const int N = 1e5+5; char s[N]; int n,nex[N], L; void GetNext(){ nex[1] = 0; for(int i=2 ,j=0 ;i<=L ;i++){ while(j &&s[i] != s[j+1]) j = nex[j]; if(s[i] == s[j+1]) j++; nex[i] = j; } } int main(){ scanf("%d",&n); for(int i=1 ;i<=n ;i++){ scanf("%s",s+1); L = strlen(s+1); GetNext(); int len = L - nex[L]; if(L % len == 0) printf("%d\n",len == L? L:0); else printf("%d\n",len - L%len); } return 0; }