题意:求n个字符串的长公共子序列;
题解:暴力出第一个序列的字串,最多有60*60种,然后根据字串进行匹配。
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
const int maxn=1e5+10;
string str[50];
int F[maxn];
void init(string s)//获取next数组,我比较喜欢用F
{
memset(F,-1,sizeof(F));
for(int i=1;i<s.size();i++)
{
int j=F[i-1];
while(s[j+1]!=s[i]&&j>=0)
j=F[j];
if(s[j+1]==s[i])
F[i]=j+1;
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{ int n;
scanf("%d",&n);
for(int i=0;i<n;i++)cin>>str[i];
string ans="";
for(int i=0;i<str[0].size();i++)//枚举起点
{ if(str[0].size()-i<ans.size())break;//这一句话一定要有,相当于剪枝。
//当当前答案已经走比后面还长的序列了,就不用继续枚举了。
for(int j=2;j<=str[0].size()-i;j++)//枚举长度。
{
bool flag=true;
string res=str[0].substr(i,j);
//cout<<res<<endl;
init(res);
// cout<<res<<endl;
for(int i=1;i<n;i++)//枚举每一个字符串
{
bool ok=false;
int u=0,d=0;
while(u<str[i].size())//匹配每一个字符串
{
if(str[i][u]==res[d])
{
u++;
d++;
if(d==res.size())//若匹配成功
{
ok=true;
break;
}
}
else//否则继续匹配
{
if(d==0)u++;
else d=F[d-1]+1;
}
}
if(!ok)//如果没有匹配成功
{
flag=false;
break;
}
}
if(flag)//若匹配成功了
{
if(res.size()>ans.size())ans=res;
if(res.size()==ans.size()&&ans>res)ans=res;
}
}
}
if(ans.size()<3)cout<<"no significant commonalities"<<endl;
else cout<<ans<<endl;
}
}