题目链接: http://exercise.acmcoder.com/online/online_judge_ques?ques_id=3368&konwledgeId=40
解题思路: 首先,我们检查一下一个字符串是否在另一个字符串当中出现过,可以把出现过的字符串全都删除。
然后对于互相不包含的字符串,我们预处理出来每对字符串拼接在一起的最大可重叠部分是多少。
最后,可以暴力枚举每中可能的组合情况,计算最有答案。例如,有3个互不包含的字符串,那么存在的组合就是,123,132,213,231,312,321.
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 const int MAXN=100005; 6 const LL MOD7 = 1e9+7; 7 8 string s[15]; 9 int a[15][15]; 10 int n; 11 12 void solve() 13 { 14 int ans=10*1000; 15 vector<int> v; 16 for (int i=0;i<n;++i) 17 { 18 v.push_back(i); 19 } 20 int tmp=s[v[0]].length(); 21 for (int i=1;i<n;++i) 22 { 23 tmp+=s[v[i]].length()-a[v[i-1]][v[i]]; 24 } 25 ans=min(ans,tmp); 26 while (next_permutation(v.begin(),v.end())) 27 { 28 tmp=s[v[0]].length(); 29 for (int i=1;i<n;++i) tmp+=s[v[i]].length()-a[v[i-1]][v[i]]; 30 ans=min(ans,tmp); 31 } 32 printf("%d\n",ans); 33 } 34 int calCommonString(string a,string b) 35 { 36 // cout<<"cal: "<<a<<"\t"<<b<<endl; 37 int lena=a.length(); 38 int lenb=b.length(); 39 for (int i=min(lena,lenb)-1;i>=1;--i) 40 { 41 // cout<<"sub: "<<a.substr(lena-i,i)<<"\t"<<b.substr(0,i)<<endl; 42 if (a.substr(lena-i,i)==b.substr(0,i)) 43 return i; 44 } 45 return 0; 46 } 47 48 int main() 49 { 50 #ifndef ONLINE_JUDGE 51 freopen("test.txt","r",stdin); 52 #endif // ONLINE_JUDGE 53 scanf("%d",&n); 54 for (int i=0;i<n;++i) cin>>s[i]; 55 int mask[15]{0}; 56 for (int i=0;i<n;++i) 57 { 58 for (int j=i+1;j<n;++j) 59 { 60 if (s[i].find(s[j])!=-1) mask[j]=1; 61 if (s[j].find(s[i])!=-1) mask[i]=1; 62 } 63 } 64 int m=0; 65 for (int i=0;i<n;++i) 66 if (!mask[i]) s[m++]=s[i]; 67 n=m; 68 // cout<<"n=m"<<n; 69 for (int i=0;i<n;++i) 70 { 71 for (int j=i+1;j<n;++j) 72 { 73 a[i][j]=calCommonString(s[i],s[j]); 74 a[j][i]=calCommonString(s[j],s[i]); 75 } 76 } 77 // for (int i=0;i<n;++i) cout<<s[i]<<endl; 78 // for (int i=0;i<n;++i) 79 // { 80 // for (int j=0;j<n;++j) cout<<a[i][j]<<" ";cout<<endl; 81 // } 82 solve(); 83 return 0; 84 }