题意:给n个字符串,输出他们的字典序最小的最长上升子序列(子序列定义为长度不超过8的,每个串自身和自身拼接后的子序列)。
思路:最多10个样例,字符串最多10个,每个串长度最多为8,指数级别都可以接受。。就暴力递归找出其中一个串的所有可能的子序列,答案一定是其中一个,排序后(长度为第一优先级,字典序为第二优先级)依次与其他串匹配,看能否和其他所有串匹配成功,若可以,就返回这个串。若所有子序列匹配不成功,输出0。
注意:和其他所有串匹配的时候,因为子序列可以循环拼接,要把这个串所有长度为n的子序列都匹配一遍,只要有一个能匹配就可以。
AC代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<set>
using namespace std;
string s[15];
int f[20][20],n;
void Getsubstrextend( string& src, int pos, string substr, vector<string>& vec)
{
if( pos == src.size() )
{
if(substr!="")
vec.push_back(substr);
return;
}
string subnewstr=substr+src[pos];
Getsubstrextend(src, pos+1, substr, vec);
Getsubstrextend(src, pos+1, subnewstr, vec);
}
void get_tem(string& scr, vector<string>& vec) //找出所有的子序列
{
int n=scr.size();
for(int i=0;i<n/2;i++)
{
string ss(scr,i,n/2);
Getsubstrextend(ss, 0, "",vec);
}
}
bool cmp(string a,string b)
{
int la=a.size(),lb=b.size();
if(la==lb)
return a<b;
return la>lb;
}
string get_ans(vector<string>& vec)
{
for(int k=0;k<vec.size();k++)
{
string a=vec[k];
int flag=1; //标记能否与其他所有串匹配
for(int kk=2;kk<=n;kk++)
{
int flag2=0; //标记能否和当前串匹配
string x=s[kk];int len=x.size();
for(int kkk=0;kkk<len/2;kkk++)
{
string b(x,kkk,len/2);
memset(f,0,sizeof f);
int la=a.size(),lb=b.size();
for(int i=1;i<=la;i++)
for(int j=1;j<=lb;j++)
{
f[i][j]=max(f[i-1][j],f[i][j-1]);
if(a[i-1]==b[j-1])
f[i][j]=max(f[i][j],f[i-1][j-1]+1);
}
if(f[la][lb]==la) //只要有一个子序列能匹配,就跳出
{
flag2=1;break;
}
}
if(!flag2) //只要有一个不满足,说明该子序列不是答案
{
flag=0;break;
}
}
if(flag==1) //和其他n-1个串都能匹配
return a;
}
return "0"; //所有都不满足,返回0
}
int main()
{
cin.tie(0);
ios::sync_with_stdio(false);
while(cin>>n)
{
for(int i=1;i<=n;i++)
{
cin>>s[i];
s[i]+=s[i];
}
vector<string> vec;
get_tem(s[1],vec);
sort(vec.begin(),vec.end(),cmp);
cout<<get_ans(vec)<<endl;
}
return 0;
}