給一些字符串,求它們的最長公共子串。
這道題數據量很小,可以直接暴力枚舉。枚舉第一個字符串的每個子串與其逆序串,kmp判斷是否在其他所有的字符串當中,之後再取其中最長的長度,輸出即可。
代碼:
//Memory: 232K Time: 63MS
//Language: C++ Result: Accepted
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
char s[105][105];
int n;
char t[105];
char _t[105];
int next[2][105];
void GetNext(char* t,int x){
int i=-1,j=0,len=strlen(t);
next[x][0]=-1;
while(j<len){
if(i==-1 || t[i]==t[j]){
if(t[++i]==t[++j]) next[x][j]=next[x][i];
else next[x][j]=i;
}
else i=next[x][i];
}
}
bool kmp(){
int i=0,j=0,len=strlen(t),lens;
GetNext(t,0);
GetNext(_t,1);
for(int k=1;k<n;k++){
lens=strlen(s[k]);
if(len>lens) return false;
i=0;j=0;
while(i<len && j<lens){
if(i==-1 || t[i]==s[k][j]) {i++;j++;}
else i=next[0][i];
}
if(i>=len) continue;
else {
i=0;j=0;
while(i<len && j<lens){
if(i==-1 || _t[i]==s[k][j]) {i++;j++;}
else i=next[1][i];
}
if(i<len) return false;
}
}
return true;
}
int main(){
//freopen("in.txt","r",stdin);
int T; cin>>T;
while(T--){
int ans=0;
cin>>n;
for(int i=0;i<n;i++){
scanf("%s",s[i]);
}
for(int i=0;i<strlen(s[0]);i++){
memset(t,0,sizeof(t));
memset(_t,0,sizeof(_t));
for(int j=i;j<strlen(s[0]);j++){
for(int k=0;i+k<=j;k++){
t[k]=s[0][i+k];
_t[k]=s[0][j-k];
}
if(kmp()) ans=(ans>(j-i+1))?ans:(j-i+1);
}
}
cout<<ans<<endl;
}
return 0;
}