POJ? 2406 题意:求最长循环节 题解:Next数组的使用,判断 len/ (len-Next[len]), 注意Next[] != 0要特别判断一下;? ![]() #include <cstring> #include <iostream> #include <cstdio> using namespace std; const int maxn=1e6 5; int Next[maxn], m, n; char x[maxn], y[maxn]; void KMP_Pre() { int i=0, j=-1; Next[0]=-1; while(i<m) { while(j!=-1 && x[i]!=x[j]) j=Next[j]; Next[ i]= j; } } int main() { ios::sync_with_stdio(false); //freopen("in.txt", "r", stdin); while(cin>>x, x[0]!='.') { m=strlen(x); int ans=1; KMP_Pre(); if(m%(m-Next[m])==0) ans=m/(m-Next[m]); cout<<ans<<endl; } return 0; }View Code ? HDU 3746 题意: 补齐循环节,求最少添加多少个字符,能获得循环节 题解:画个图看看就行了,可发现 (len x)/ (len x-Next[len] x) 注意Next[] != 0要特别判断一下; ![]() #include <cstring> #include <iostream> #include <cstdio> using namespace std; const int maxn=1e6 5; int Next[maxn], m, n; char x[maxn], y[maxn]; void KMP_Pre() { int i=0, j=-1; Next[0]=-1; while(i<m) { while(j!=-1 && x[i]!=x[j]) j=Next[j]; Next[ i]= j; } } int main() { ios::sync_with_stdio(false); //freopen("in.txt", "r", stdin); int T; cin>>T; while(T--) { cin>>x; m=strlen(x); KMP_Pre(); int ans; if(Next[m]!=0 && m%(m-Next[m])!=0) ans=(m-Next[m])-m%(m-Next[m]); else if(Next[m]==0) ans=m; else ans=0; cout<<ans<<endl; } return 0; }View Code ? HDU 1358 题意:求前缀的循环节 题解:和前面一样直接判断取余后是否有余数即可 ![]() #include <cstring> #include <iostream> #include <cstdio> using namespace std; const int maxn=1e6 5; int Next[maxn], m, n; char x[maxn], y[maxn]; void KMP_Pre() { int i=0, j=-1; Next[0]=-1; while(i<m) { while(j!=-1 && x[i]!=x[j]) j=Next[j]; Next[ i]= j; } } int main() { ios::sync_with_stdio(false); //freopen("in.txt", "r", stdin); int kase=0; while(cin>>m, m) { cin>>x; KMP_Pre(); printf("Test case #%d\n", kase); for(int i=2; i<=m; i ) { if(Next[i]>0 && i%(i-Next[i])==0) printf("%d %d\n", i, i/(i-Next[i])); } printf("\n"); } return 0; }View Code ? HDU 2087? 题意:求子串在母串出现的次数(不重叠) 题解:每次匹配完成后讲j指向0即可 ![]() #include <cstring> #include <iostream> #include <cstdio> using namespace std; const int maxn=1e5 5; int Next[maxn], m, n; char x[maxn], y[maxn]; void KMP_Pre() { int i=0, j=-1; Next[0]=-1; while(i<m) { while(j!=-1 && x[i]!=x[j]) j=Next[j]; Next[ i]= j; } } int KMP_Count() { int i=0, j=0; int ans=0; KMP_Pre(); while(i<n) { while(j!=-1 && y[i]!=x[j]) j=Next[j]; i ; j ; if(j>=m){ ans ; j=0; } } return ans; } int main() { ios::sync_with_stdio(false); //freopen("in.txt", "r", stdin); while(cin>>y>>x, y[0]!='#') { m=strlen(x); n=strlen(y); cout<<KMP_Count()<<endl; } return 0; }View Code ? POJ 2752? 题意:求既是前缀又是后缀的子串长度 ;? 题解:这题比之前的要难一点,这个是非常清晰Next数组和KMP算法的过程;? Next数组记录的就是前缀串,若Next[len]==s[len-1] 即前后缀相等,然后不断迭代Next[len]并判断即可,然后判断s[next[next[n-1]]] == s[n-1]是否成立,这样一直回滚,直到next[next[.....next[n-1]]] == -1为止。 ![]() #include <cstring> #include <iostream> #include <cstdio> using namespace std; const int maxn=1e6 5; int Next[maxn], m, n; char x[maxn], y[maxn]; void KMP_Pre() { int i=0, j=-1; Next[0]=-1; while(i<m) { while(j!=-1 && x[i]!=x[j]) j=Next[j]; Next[ i]= j; } } int ans[maxn]; int main() { ios::sync_with_stdio(false); //freopen("in.txt", "r", stdin); while(cin>>x) { m=strlen(x); KMP_Pre(); int pre=m-1, cnt=1; while(pre!=-1) { if(x[pre]==x[m-1]) ans[cnt ]=pre 1; pre=Next[pre]; } while(--cnt) cout<<ans[cnt]<<" "; cout<<endl; } return 0; }View Code ? POJ 3080 题意:找多个串之间的公共子串,输出最大的(数据量很小) 题解:暴力截取 KMP匹配判断,维护一个最大的即可;? ![]() #include <cstdio> #include <iostream> #include <cstring> #include <string> using namespace std; string str[100], s[100]; int Next[100]; void KMP_Pre(string x, int m) { int i=0, j=-1; Next[0]=-1; while(i<m) // 这个之前错写成j<m { while(j!=-1 && x[i]!=x[j]) j=Next[j]; Next[ i]= j; } } bool KMP(string x, int m, string y, int n) { //KMP_Pre(x, m); int i=0, j=0; while(i<n) { while(j!=-1 && y[i]!=x[j]) j=Next[j]; i; j; if(j>=m) return true; } return false; } int main() { //freopen("in.txt", "r", stdin); int T; cin>>T; while(T--) { int num; cin>>num; for(int i=0; i<num; i ) cin>>str[i]; string ans=""; for(int len=1; len<=str[0].size(); len ) //这个等于之前丢了... for(int i=0; i len<=str[0].size(); i ) { bool flag=1; string p=str[0].substr(i, len); KMP_Pre(p, p.size()); for(int k=1; k<num; k ) if( !KMP(p, p.size(), str[k], str[k].size()) ){ flag=0; break; } if(flag) { if(ans.size()<p.size()) ans=p; else if(ans.size()==p.size()) ans=min(ans,p); } } if(ans.size()<3) cout<<"no significant commonalities"<<endl; else cout<<ans<<endl; } return 0; }View Code ? 来源:http://www./content-1-183551.html |
|