P3881
Forever1507 · · 题解
爆搜就行了,对,就是爆搜。
考虑此时你手上有俩字符串
然后设
那么,只要在最开始枚举两个串,使得其中一个是另一个的前缀,以它们为
当然直接这么搜会寄,加一个比较强的剪枝:
当前的这两个串的长度若超过已有最小值,停下来,不搜了,反正对答案没贡献。
还有一个细节,初始答案设
代码:
#include<bits/stdc++.h>
using namespace std;
int n;
string s[25];
string ans;
int len=400;
bool cmp(string s1,string s2){
return s1.size()>s2.size();
}
void dfs(string s1,string s2){//s1长
if(s1.size()>len||s2.size()>len)return;//大力剪枝
if(s1.size()==s2.size()){
if(len>s1.size()){
len=s1.size();//更新答案
if(ans==""||ans.size()>s1.size())ans=s1;
else ans=min(ans,s1);
}
return;
}
if(s1.size()<s2.size())swap(s1,s2);//保证s1更长
int m=s1.size()-s2.size();
for(int i=1;i<=n;++i){
if(s[i].size()>=m){//s'是s[i]的前缀
string _s="";
for(int i=s2.size();i<s1.size();++i)_s+=s1[i];
if(s[i].substr(0,m)==_s)dfs(s1,s2+s[i]);
}
else{//反之
if(s1.substr(s2.size(),s[i].size())==s[i])dfs(s1,s2+s[i]);
}
}
return;
}
int main(){
cin>>n;
for(int i=1;i<=n;++i)cin>>s[i];
sort(s+1,s+n+1,cmp);//按长度排序,不然substr会挂
for(int i=1;i<=n;++i){
for(int j=i+1;j<=n;++j){
if(s[i].substr(0,s[j].size())==s[j]){
dfs(s[i],s[j]);
}
}
}
cout<<len<<'\n'<<ans;
return 0;
}