版权声明:本文为博主原创文章,转载请预先通知博主(〃'▽'〃)。 https://blog.csdn.net/m0_37624640/article/details/82817071
题意:
- 找出这n个串的最长公共子序列,我们把每个串都看成环,子序列可以从环中找出。
- 其中要保证公共子序列的字典序最小。
- 比如:
-
abcdef kedajceu
- 其中他们的公共子序列是 acd
做法:
- 每个串的长度最多不超过8,最多10组数据,显然我们可以通过状态压缩枚举子集找到所有的子串。
- 由于每个串是环状的,所以我们把串加倍,模拟成环,枚举第一个串s1所有长度为len(s1)的子串去暴力判断其他串即可。
#include<bits/stdc++.h>
#define IO ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pb(x) push_back(x)
#define sz(x) (int)(x).size()
#define sc(x) scanf("%d",&x)
#define pr(x) printf("%d\n",x)
#define abs(x) ((x)<0 ? -(x) : x)
#define all(x) x.begin(),x.end()
#define mk(x,y) make_pair(x,y)
#define debug printf("!!!!!!\n")
#define fin freopen("in.txt","r",stdin)
#define fout freopen("out.txt","w",stdout)
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const double PI = 4*atan(1.0);
const int maxm = 1e8+5;
const int maxn = 1e5+5;
const int INF = 0x3f3f3f3f;
string s[20],tmp,ans;
bool check(int x)
{
int p1 = 0,p2 = 0;
int st = INF;
while(p1<(int)s[x].length() && p2<(int)tmp.length())
{
if(s[x][p1] == tmp[p2]){
p1++;
p2++;
if(p2 == 1) st = p1-1;
}
else{
if(tmp[0] == s[x][p1] && p2 == 1){
st = p1;
}
p1++;
}
}
return (p1-st<=(int)s[x].length()/2) && (p2 ==(int)tmp.length());
}
int main()
{
#ifdef LOCAL_FILE
fin;
#endif // LOCAL_FILE
IO;
int n;
while(cin>>n)
{
ans = "";
for(int i=1;i<=n;i++){
cin>>s[i];
s[i]+=s[i];//加倍
}
int len = s[1].length()/2;
for(int l=0;l<len;l++)
{
for(int S=1;S<(1<<len);S++)
{
tmp = "";
int res = 0;
for(int i=0;i<len;i++)
{
if(S&(1<<i)) tmp+=s[1][i+l];
}
for(int i=2;i<=n;i++) res+=check(i);
if(res == n-1)
{
if(tmp.length()>ans.length())
ans = tmp;
else if(tmp.length() == ans.length())
if(ans>tmp) ans = tmp;
}
}
}
if(sz(ans) == 0) cout<<0<<endl;
else cout<<ans<<endl;
}
return 0;
}