1:练习了string类,string中查找,找不到的话会返回 s.npos一个变量,而不是返回一般的s.end();
2:这题还可以,ac自动机上状压bfs,找最短路,实际上是dp,但是转移都是加1,所以可以抽象为边长为一从起始状态到最终状态的最短路,因为为边长1,又可以转为bfs。
3:
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<string>
#include<iostream>
using namespace std;
const int inf=0x3f3f3f3f;
int n;
string s[15],tmp1,tmp2,tmp;
struct aa
{
int len,preS,preJ;
}f[(1<<12)+5][15];
int c[15][15],len[15];
bool b[15];
string get(int S,int J)
{
int preJ;
string tmp=s[J];
while (f[S][J].preS!=0)
{
preJ=f[S][J].preJ;
tmp+=s[preJ].substr(c[J][preJ],len[preJ]-c[J][preJ]);
S=f[S][J].preS,J=preJ;
}
return tmp;
}
int main()
{
cin>>n;
for (int i=0;i<n;i++) cin>>s[i];
for (int i=0;i<n;i++)
for (int j=i+1;j<n;j++)
{
if (s[j].find(s[i])!=s[j].npos) b[i]=true;
if (s[j]==s[i]) continue;
if (s[i].find(s[j])!=s[i].npos) b[j]=true;
}
for (int i=0;i<n;)
if (b[i])
{
n--;
for (int j=i;j<n;j++) s[j]=s[j+1],b[j]=b[j+1];
}else i++;
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
if (i!=j)
{
int l1=s[i].length(),l2=s[j].length();
for (int k=min(l1,l2)-1;k>=1;k--)
if (s[i].substr(l1-k,k)==s[j].substr(0,k)) {c[i][j]=k;break;}
}
for (int i=0;i<(1<<n);i++) for (int j=0;j<n;j++) f[i][j].len=inf;
for (int i=0;i<n;i++) f[1<<i][i].len=len[i]=s[i].length();
for (int i=0;i<(1<<n);i++)
for (int j=0;j<n;j++)
if (f[i][j].len!=inf)
{
tmp=get(i,j);
for (int k=0;k<n;k++) if (!(i&(1<<k)))
{
bool o=false;
if (f[i|(1<<k)][k].len>f[i][j].len+len[k]-c[k][j]) o=true;
else if (f[i|(1<<k)][k].len==f[i][j].len+len[k]-c[k][j])
{
tmp1=get(i|(1<<k),k);
tmp2=s[k].substr(0,len[k]-c[k][j])+tmp;
if (tmp2<tmp1) o=true;
}
if (o)
{
f[i|(1<<k)][k].len=f[i][j].len+len[k]-c[k][j];
f[i|(1<<k)][k].preJ=j;
f[i|(1<<k)][k].preS=i;
}
}
}
int S=(1<<n)-1,mi=inf;
for (int i=0;i<n;i++)
if (f[S][i].len<mi||(f[S][i].len==mi&&get(S,i)<tmp)) mi=f[S][i].len,tmp=get(S,i);
cout<<tmp;
return 0;
}