(29/29) 3.23已完成
1.KMP
int Next[maxn]; void prekmp(char* x,int len){ int pre=-1,suf=0; Next[0]=-1; while(suf<len){ while(pre!=-1&&x[suf]!=x[pre]) pre=Next[pre]; Next[++suf]=++pre; } } int kmp(char* x,char* y){ int lenx=strlen(x); int leny=strlen(y); int pre=0,suf=0,ans=0; prekmp(x,lenx); while(suf<leny){ while(pre!=-1&&y[suf]!=x[pre]) pre=Next[pre]; pre++; suf++; if(pre>=lenx){ pre=Next[pre]; ans++; } } return ans; }
模板写法及变式(待更新)
基本形
其中,next数组的0号位为缺省值-1,其余位为正常位,第len位为保留位(用于处理全部匹配情况)。
next[i]存储的是对应前i-1位的最大公共前后缀长度。
一般算法理论中讨论的前后缀都是真前后缀,即不包含自身的的前后缀,为运用方便,以后统一如此编程。
next[i]=k的意义是模式串0~k-1位与i~i+k-1位相等,方便主匹配指针(指向结尾)直接通过递归方式快速滚动(j->next[j])
所以能辨别的公共词缀最小长度为2,单字不相同与单字相同无法辨别。
这是因为next数组是经过方便指针快速滚动而改造的,默认意义下的kmp算法的核心是主指针的失配而不是指针的匹配。
HDU 1711(数字序列单模式串匹配)
要求输出第一个成功匹配的位置,匹配成功直接return就好了
模板题
//#define LOCAL #include <cstring> #include <iostream> #include <sstream> #include <fstream> #include <string> #include <vector> #include <deque> #include <queue> #include <stack> #include <set> #include <map> #include <algorithm> #include <functional> #include <utility> #include <bitset> #include <cmath> #include <cstdlib> #include <ctime> #include <cstdio> using namespace std; #define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z)) // X_INIT=0 mem_Macro #define INF (1<<29) #define MOD 1000000007ll #define FOR(i,j,k) for(int i=j;i<=k;i++) #define FORD(i,j,k) for(int i=j;i>=k;i--) #define LL long long #define SZ(x) int(x.size()) #define pb push_back #define maxn 1000010 #define maxm 10010 int a[maxn],b[maxm],Next[maxm]; int n,m,T; inline LL read(){ LL f=1,ans=0; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while('0'<=ch&&ch<='9'){ans=ans*10+ch-'0';ch=getchar();} return ans*f; } void doit(){ int pre=0; Next[0]=0,Next[1]=0; FOR(suf,2,m){ while(pre>0&&b[pre+1]!=b[suf]) pre=Next[pre]; if(b[pre+1]==b[suf]) pre++; Next[suf]=pre; } return; } void kmp(){ int pre=0,ans=-1; //Next[0]=0,Next[1]=0; FOR(suf,1,n){ while(pre>0&&b[pre+1]!=a[suf]) pre=Next[pre]; if(b[pre+1]==a[suf]) pre++; if(pre==m) {if(ans==-1) ans=suf-m+1; pre=Next[pre];} } cout<<ans<<endl; return; } int main(){ #ifdef LOCAL freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); #endif cin>>T; FOR(i,1,T){ cin>>n>>m; FOR(i,1,n) a[i]=(int) read(); FOR(i,1,m) b[i]=(int) read(); doit(); kmp(); } #ifdef LOCAL fclose(stdin); fclose(stdout); #endif //system(pause); return 0; }
HDU-1686(单模式串匹配)
要求输出匹配次数(可重叠)
模板题,匹配成功直接做失配处理
//#define LOCAL #include <cstring> #include <iostream> #include <sstream> #include <fstream> #include <string> #include <vector> #include <deque> #include <queue> #include <stack> #include <set> #include <map> #include <algorithm> #include <functional> #include <utility> #include <bitset> #include <cmath> #include <cstdlib> #include <ctime> #include <cstdio> using namespace std; #define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z)) // X_INIT=0 mem_Macro #define INF (1<<29) #define MOD 1000000007ll #define FOR(i,j,k) for(int i=j;i<=k;i++) #define FORD(i,j,k) for(int i=j;i>=k;i--) #define LL long long #define SZ(x) int(x.size()) #define pb push_back #define maxn 1000010 #define maxm 10010 char a[maxn],b[maxm]; int Next[maxm]; int n,m,t; inline LL read(){ LL f=1,ans=0; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while('0'<=ch&&ch<='9'){ans=ans*10+ch-'0';ch=getchar();} return ans*f; } void doit(){ int pre=0; Next[0]=0,Next[1]=0; FOR(suf,2,m){ while(pre>0&&b[pre+1]!=b[suf]) pre=Next[pre]; if(b[pre+1]==b[suf]) pre++; Next[suf]=pre; } return; } void kmp(){ int pre=0,ans=0; FOR(suf,1,n){ while(pre>0&&b[pre+1]!=a[suf]) pre=Next[pre]; if(b[pre+1]==a[suf]) pre++; if(pre==m) {ans++;; pre=Next[pre];} } cout<<ans<<endl; return; } int main(){ #ifdef LOCAL freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); #endif scanf("%d",&t); FOR(i,1,t){ scanf("%s",b+1); m=strlen(b+1); scanf("%s",a+1); n=strlen(a+1); doit(); kmp(); } #ifdef LOCAL fclose(stdin); fclose(stdout); #endif //system(pause); return 0; }
HDU 2087(单模式串匹配)
要求输出匹配次数(不可重叠)
模板题,以前写的是保留上次匹配的结果以检验是否可能重叠。现在看来直接将副指针归零即可
//#define LOCAL #include <cstring> #include <iostream> #include <sstream> #include <fstream> #include <string> #include <vector> #include <deque> #include <queue> #include <stack> #include <set> #include <map> #include <algorithm> #include <functional> #include <utility> #include <bitset> #include <cmath> #include <cstdlib> #include <ctime> #include <cstdio> using namespace std; #define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z)) // X_INIT=0 mem_Macro #define INF (1<<29) #define MOD 1000000007ll #define FOR(i,j,k) for(int i=j;i<=k;i++) #define FORD(i,j,k) for(int i=j;i>=k;i--) #define LL long long #define SZ(x) int(x.size()) #define pb push_back #define maxn 1000010 #define maxm 10010 char a[maxn],b[maxm]; int Next[maxm]; int n,m,t; inline LL read(){ LL f=1,ans=0; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while('0'<=ch&&ch<='9'){ans=ans*10+ch-'0';ch=getchar();} return ans*f; } void doit(){ int pre=0; Next[0]=0,Next[1]=0; FOR(suf,2,m){ while(pre>0&&b[pre+1]!=b[suf]) pre=Next[pre]; if(b[pre+1]==b[suf]) pre++; Next[suf]=pre; } return; } void kmp(){ int pre=0,ans=0,spre=0; FOR(suf,1,n){ while(pre>0&&b[pre+1]!=a[suf]) pre=Next[pre]; if(b[pre+1]==a[suf]) pre++; if(pre==m&&suf>=spre+m) {ans++; spre=suf; pre=Next[pre];} } cout<<ans<<endl; return; } int main(){ #ifdef LOCAL freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); #endif while(true){ scanf("%s",a+1); if(a[1]=='#') break; n=strlen(a+1); scanf("%s",b+1); m=strlen(b+1); doit(); kmp(); } #ifdef LOCAL fclose(stdin); fclose(stdout); #endif //system(pause); return 0; }
HDU 1711(单模式串匹配)
要求输出第一个成功匹配的位置
模板题,练手
//#define LOCAL #include <cstring> #include <iostream> #include <sstream> #include <fstream> #include <string> #include <vector> #include <deque> #include <queue> #include <stack> #include <set> #include <map> #include <algorithm> #include <functional> #include <utility> #include <bitset> #include <cmath> #include <cstdlib> #include <ctime> #include <cstdio> using namespace std; #define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z)) // X_INIT=0 mem_Macro #define INF (1<<29) #define MOD 1000000007ll #define FOR(i,j,k) for(int i=j;i<=k;i++) #define FORD(i,j,k) for(int i=j;i>=k;i--) #define LL long long #define SZ(x) int(x.size()) #define pb push_back #define maxn 1000010 #define maxm 10010 int a[maxn],b[maxm],Next[maxm]; int n,m,T; inline LL read(){ LL f=1,ans=0; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while('0'<=ch&&ch<='9'){ans=ans*10+ch-'0';ch=getchar();} return ans*f; } void doit(){ int pre=0; Next[0]=0,Next[1]=0; FOR(suf,2,m){ while(pre>0&&b[pre+1]!=b[suf]) pre=Next[pre]; if(b[pre+1]==b[suf]) pre++; Next[suf]=pre; } return; } void kmp(){ int pre=0,ans=-1; FOR(suf,1,n){ while(pre>0&&b[pre+1]!=a[suf]) pre=Next[pre]; if(b[pre+1]==a[suf]) pre++; if(pre==m) {if(ans==-1) ans=suf-m+1; pre=Next[pre];} } cout<<ans<<endl; return; } int main(){ #ifdef LOCAL freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); #endif cin>>T; FOR(i,1,T){ cin>>n>>m; FOR(i,1,n) a[i]=(int) read(); FOR(i,1,m) b[i]=(int) read(); doit(); kmp(); } #ifdef LOCAL fclose(stdin); fclose(stdout); #endif //system(pause); return 0; }
POJ 2752
求最大公共前后缀
//#define LOCAL #include <cstring> #include <iostream> #include <sstream> #include <fstream> #include <string> #include <vector> #include <deque> #include <queue> #include <stack> #include <set> #include <map> #include <algorithm> #include <functional> #include <utility> #include <bitset> #include <cmath> #include <cstdlib> #include <ctime> #include <cstdio> using namespace std; #define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z)) // X_INIT=0 mem_Macro #define INF (1<<29) #define MOD 1000000007ll #define FOR(i,j,k) for(int i=j;i<=k;i++) #define FORD(i,j,k) for(int i=j;i>=k;i--) #define LL long long #define SZ(x) int(x.size()) #define pb push_back #define maxn 1000010 #define maxm 1000010 char a[maxn],b[maxm]; int Next[maxm]; int n,m,t,len; inline LL read(){ LL f=1,ans=0; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while('0'<=ch&&ch<='9'){ans=ans*10+ch-'0';ch=getchar();} return ans*f; } void doit(){ int pre=0; Next[0]=0,Next[1]=0; FOR(suf,2,m){ while(pre>0&&b[pre+1]!=b[suf]) pre=Next[pre]; if(b[pre+1]==b[suf]) pre++; Next[suf]=pre; } return; } void kmp(){ int pre=0,ans=0; //Next[0]=0,Next[1]=0; FOR(suf,1,n){ while(pre>0&&b[pre+1]!=a[suf]) pre=Next[pre]; if(b[pre+1]==a[suf]) pre++; if(pre==m) {ans++; pre=Next[pre];} } cout<<ans<<endl; return; } int main(){ #ifdef LOCAL freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); #endif t=0; stack<int> ans; while(scanf("%s",b+1)!=EOF){ m=strlen(b+1); doit(); while(!ans.empty()) ans.pop(); ans.push(m); while(Next[m]!=0) ans.push(m=Next[m]); printf("%d",ans.top());ans.pop(); while(!ans.empty()){printf(" %d",ans.top());;ans.pop();} cout<<endl; } #ifdef LOCAL fclose(stdin); fclose(stdout); #endif //system(pause); return 0; }
POJ 3080
确定多个串的最大公共子串,穷举答案即可(就用第一个字符串)
穷举答案也是字符串题常见操作了,固定起点的话记得一失配就break掉
//#define LOCAL #include <cstring> #include <iostream> #include <sstream> #include <fstream> #include <string> #include <vector> #include <deque> #include <queue> #include <stack> #include <set> #include <map> #include <algorithm> #include <functional> #include <utility> #include <bitset> #include <cmath> #include <cstdlib> #include <ctime> #include <cstdio> using namespace std; #define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z)) // X_INIT=0 mem_Macro #define INF 0x3f3f3f3f #define MOD 1000000007 #define FOR(i,j,k) for(int i=j;i<k;i+=1) #define FORD(i,j,k) for(int i=j;i>k;i-=1) #define uLL unsigned long long #define LL long long #define SZ(x) int(x.size()) #define pb push_back #define maxn 70 int Next[maxn]; int lens[maxn]; char s[maxn][maxn]; char xx[maxn]; void prekmp(char x[],int len){ int pre=-1,suf=0; Next[0]=-1; while(suf<len){ while(pre!=-1&&x[suf]!=x[pre]) pre=Next[pre]; Next[++suf]=++pre; } } int kmp(int lenx,char *x,int leny,char *y){ //int lenx=strlen(x); //int leny=strlen(y); int pre=0,suf=0,ans=0;//FOR(i,0,lenx) cout<<x[i]<<"**"; prekmp(x,lenx); while(suf<leny){ while(pre!=-1&&y[suf]!=x[pre]) pre=Next[pre]; pre++; suf++; if(pre>=lenx){ pre=Next[pre]; ans++; } } return ans; } int main(){ #ifdef LOCAL freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); #endif int T,n,cnt,flag,jj=0; scanf("%d",&T); while(T--){ scanf("%d",&n); FOR(i,0,n){ scanf("%s",s[i]); lens[i]=strlen(s[i]); } int len0=strlen(s[0]); int maxlen=-1,leni=0,lenj=0; FOR(i,0,len0-2){ cnt=-1; xx[++cnt]=s[0][i]; FOR(j,i+1,len0){ xx[++cnt]=s[0][j]; flag=true; jj=j; FOR(k,1,n) if(!kmp(cnt+1,xx,lens[k],s[k])) {flag=false;break;} if(!flag) {jj--;break;} } if(jj-i>1){ if(maxlen<jj-i+1) {maxlen=jj-i+1;leni=i;lenj=jj;} else if(maxlen==jj-i+1){ FOR(p,0,jj-i+1) if(s[0][leni+p]>s[0][i+p]){maxlen=jj-i+1;leni=i;lenj=jj;break;} } } } if(maxlen!=-1) FOR(p,leni,lenj+1) printf("%c",s[0][p]); else printf("no significant commonalities"); if(T!=0) printf(" "); } //system("pause"); #ifdef LOCAL fclose(stdin); fclose(stdout); #endif return 0; }
hdu 2594
求S1的前缀和S2的后缀的最大匹配
建立新字符串S=S1+S2 跑个next,然后递归next[lens1+lens2],找到第一个小于lens1的next[]
//#define LOCAL #include <cstring> #include <iostream> #include <sstream> #include <fstream> #include <string> #include <vector> #include <deque> #include <queue> #include <stack> #include <set> #include <map> #include <algorithm> #include <functional> #include <utility> #include <bitset> #include <cmath> #include <cstdlib> #include <ctime> #include <cstdio> using namespace std; #define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z)) // X_INIT=0 mem_Macro #define INF (1<<29) #define MOD 1000000007ll #define FOR(i,j,k) for(int i=j;i<=k;i++) #define FORD(i,j,k) for(int i=j;i>=k;i--) #define LL long long #define SZ(x) int(x.size()) #define pb push_back #define maxn 200010 #define maxm 200010 char a[maxn],b[maxm]; int Next[maxm]; int n,m,t,len; inline LL read(){ LL f=1,ans=0; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while('0'<=ch&&ch<='9'){ans=ans*10+ch-'0';ch=getchar();} return ans*f; } void doit(){ int pre=0; Next[0]=0,Next[1]=0; FOR(suf,2,m){ while(pre>0&&b[pre+1]!=b[suf]) pre=Next[pre]; if(b[pre+1]==b[suf]) pre++; Next[suf]=pre; } return; } void kmp(){ int pre=0,ans=0; //Next[0]=0,Next[1]=0; FOR(suf,1,n){ while(pre>0&&b[pre+1]!=a[suf]) pre=Next[pre]; if(b[pre+1]==a[suf]) pre++; if(pre==m) {ans++; pre=Next[pre];} } cout<<ans<<endl; return; } int main(){ #ifdef LOCAL freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); #endif t=0; //stack<int> ans; while(scanf("%s%s",b+1,a+1)!=EOF){ m=strlen(b+1); n=strlen(a+1); FOR(i,1,n) b[i+m]=a[i]; int lm=m; m+=n;//cout<<n; doit(); if(lm==1) {if(b[1]==b[m]) printf("%c 1 ",b[1]); else printf("0 "); } else if(Next[m]){ while(Next[m]>lm||Next[m]>n) m=Next[m]; FOR(i,1,Next[m]) printf("%c",b[i]); printf(" %d ",Next[m]); } else printf("0 "); } #ifdef LOCAL fclose(stdin); fclose(stdout); #endif //system(pause); return 0; }
hdu 3336
给出字符串S, 输出S所有前缀的出现次数之和
显然的,有s[0~k-1]的所有前缀的出现次数之和=s[0~next[k]]的所有前缀的出现次数之和+s[0~next[k]]这个最大的公共前后缀
为了省事直接push型dp。
不显然的,这题应该有更深的理解,remain update
//#define LOCAL #include <cstring> #include <iostream> #include <sstream> #include <fstream> #include <string> #include <vector> #include <deque> #include <queue> #include <stack> #include <set> #include <map> #include <algorithm> #include <functional> #include <utility> #include <bitset> #include <cmath> #include <cstdlib> #include <ctime> #include <cstdio> using namespace std; #define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z)) // X_INIT=0 mem_Macro #define INF 0x3f3f3f3f #define MOD 1000000007 #define FOR(i,j,k) for(int i=j;i<k;i+=1) #define FORD(i,j,k) for(int i=j;i>k;i-=1) #define uLL unsigned long long #define LL long long #define SZ(x) int(x.size()) #define pb push_back #define maxn 200010 int t,n; char x[maxn]; int Next[maxn],f[maxn]; void prekmp(char* x,int len){ int pre=-1,suf=0; Next[0]=-1; while(suf<=len){ while(pre!=-1&&x[suf]!=x[pre]) pre=Next[pre]; Next[++suf]=++pre; } } int kmp(char* x,int lenx,char* y,int leny){ //int lenx=strlen(x); //int leny=strlen(y); int pre=0,suf=0,ans=0; while(suf<leny){ while(pre!=-1&&y[suf]!=x[pre]) pre=Next[pre]; pre++; suf++; if(pre>=lenx){ pre=Next[pre]; ans++; } } return ans; }int dp[maxn]; int main(){ #ifdef LOCAL freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); #endif scanf("%d",&t); FOR(i,0,t){ int ans; scanf("%d",&n); scanf("%s",x); memset(Next,0,sizeof(Next)); memset(dp,0,sizeof(dp)); prekmp(x,n); dp[0]=0; ans=0; FOR(j,1,n+1) { dp[j]=(dp[Next[j]]+1)%10007; ans+=dp[j]; ans=ans%10007; } printf("%d ",ans); } #ifdef LOCAL fclose(stdin); fclose(stdout); #endif return 0; }
hdu 1238
n个串的最大公共子串,这里的子串要求其本身匹配或者其倒转串匹配
枚举答案题的加强版,依然是善用break
//#define LOCAL #include <cstring> #include <iostream> #include <sstream> #include <fstream> #include <string> #include <vector> #include <deque> #include <queue> #include <stack> #include <set> #include <map> #include <algorithm> #include <functional> #include <utility> #include <bitset> #include <cmath> #include <cstdlib> #include <ctime> #include <cstdio> using namespace std; #define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z)) // X_INIT=0 mem_Macro #define INF 0x3f3f3f3f #define MOD 1000000007 #define FOR(i,j,k) for(int i=j;i<k;i+=1) #define FORD(i,j,k) for(int i=j;i>k;i-=1) #define uLL unsigned long long #define LL long long #define SZ(x) int(x.size()) #define pb push_back #define maxn 210 char s[4050][maxn]; char xx[maxn]; int len[maxn]; int t,ans,cnt,flag,leni,lenj; int Next[maxn]; void prekmp(char* x,int len){ int pre=-1,suf=0; Next[0]=-1; while(suf<len){ while(pre!=-1&&x[suf]!=x[pre]) pre=Next[pre]; Next[++suf]=++pre; } } int kmp(char* x,int lenx,char* y,int leny){ //int lenx=strlen(x); //int leny=strlen(y); int pre=0,suf=0,ans=0; prekmp(x,lenx); while(suf<leny){ while(pre!=-1&&y[suf]!=x[pre]) pre=Next[pre]; pre++; suf++; if(pre>=lenx){ pre=Next[pre]; ans++; return ans; } } return ans; } int main(){ #ifdef LOCAL freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); #endif int pp; scanf("%d",&pp); FOR(ppp,0,pp){ scanf("%d",&t); ans=-1; FOR(i,0,t){ cin>>s[i];len[i]=strlen(s[i]);} FOR(i,0,len[0]){ cnt=0; flag=true; FOR(j,i,len[0]){ xx[cnt++]=s[0][j]; FOR(k,1,t) if(!kmp(xx,cnt,s[k],len[k])){ reverse(xx,xx+cnt); if(!kmp(xx,cnt,s[k],len[k])) {reverse(xx,xx+cnt);flag=false;break;} reverse(xx,xx+cnt); } if(flag) ans=max(ans,cnt-1); } } printf("%d ",ans+1); } //system("pause"); #ifdef LOCAL fclose(stdin); fclose(stdout); #endif return 0; }
反转函数reverse
虽然这玩意poj是ban掉的。。。。用法是reverse(x.begin(),x.end())。常用且善用!!!!
hdu 2328
n个串的最大公共子串,多测,数据鬼畜,愣是卡掉了我的代码,至今不知道自己怎么错的。。。
#include <cstring> #include <iostream> #include <sstream> #include <fstream> #include <string> #include <vector> #include <deque> #include <queue> #include <stack> #include <set> #include <map> #include <algorithm> #include <functional> #include <utility> #include <bitset> #include <cmath> #include <cstdlib> #include <ctime> #include <cstdio> using namespace std; const int N = 205, M = 4005; char s[M][N], p[N], ans[N]; int m, mx, t, k, ne[N]; void getNext() { ne[1] = 0; for (int i = 2, j = 0; i <= m; i++) { while (j && p[i] != p[j + 1]) j = ne[j]; if (p[i] == p[j + 1]) j++; ne[i] = j; } } bool kmp(int k) { int n = strlen(s[k] + 1); getNext(); for (int i = 1, j = 0; i <= n; i++) { while (j && s[k][i] != p[j + 1]) j = ne[j]; if (s[k][i] == p[j + 1]) j++; if (j == m) return true;//匹配成功 } return false; } bool ok() { for (int i = 1; i <= k; i++) { if (!kmp(i)) return false; } return true; } int main() { while (scanf("%d", &k), k) { for (int i = 1; i <= k; i++) scanf("%s", s[i] + 1); //枚举所有字串 int n = strlen(s[1] + 1); mx = 0; for (int i = 1; i <= n; i++) { for (int j = i; j <= n; j++) { for (int h = i; h <= j; h++) p[h - i + 1] = s[1][h]; m = j - i + 1; p[m + 1] = '