[HNOI2006]最短母串问题
题目大意:给定一个字符串集,求一个最短字串,使得该集合内的串都是该串的一个子串
算法:AC自动机+最短路+状压DP
注意空间限制
#include"cstdio"
#include"cstring"
#include"iostream"
#include"algorithm"
#include"bitset"
#include"string"
using namespace std;
const int MAXN=13;
const int MAXM=55;
const int siz=26;
int n,cnt,minn;
string ans;
short q[MAXN*MAXM*siz];
int ln[MAXN*MAXM],f[MAXN][MAXN],I[MAXN][1<<12];
string G[MAXN*MAXM],g[MAXN][MAXN],H[MAXN][1<<12];
int rid[MAXN];
char ch[MAXM*MAXN];
bitset<MAXN*MAXM> vis;
struct rpg{
int fail;
int sn[siz];
}T[MAXN*MAXM];
void ins(char *ch,int id)
{
int ln=strlen(ch+1),nw=0;
for(int i=1;i<=ln;++i){
if(!T[nw].sn[ch[i]-'A']) T[nw].sn[ch[i]-'A']=++cnt;
nw=T[nw].sn[ch[i]-'A'];
}rid[id]=nw;
return;
}
void Getfail()
{
int hd=1,tl=0;
for(int i=0;i<siz;++i) if(T[0].sn[i]) q[++tl]=T[0].sn[i];
while(hd<=tl){
int nw=q[hd++];
for(int i=0;i<siz;++i){
if(T[nw].sn[i]){
T[T[nw].sn[i]].fail=T[T[nw].fail].sn[i];
q[++tl]=T[nw].sn[i];
}else T[nw].sn[i]=T[T[nw].fail].sn[i];
}
}return;
}
void SPFA(int s)
{
int hd=1,tl=1;
memset(ln,0x7f,sizeof(ln));
for(int i=1;i<=cnt;++i) G[i].clear();
q[hd]=s;ln[s]=0;vis[s]=1;
while(hd<=tl){
int nw=q[hd++];vis[nw]=0;
if(ln[T[nw].fail]>ln[nw]){
ln[T[nw].fail]=ln[nw];
G[T[nw].fail]=G[nw];
if(!vis[T[nw].fail]){
vis[T[nw].fail]=1;
q[++tl]=T[nw].fail;
}
}for(int i=0;i<siz;++i){
string str=G[nw]+(char)(i+'A');
if(ln[T[nw].sn[i]]<ln[nw]+1) continue;
if(ln[T[nw].sn[i]]>ln[nw]+1){
ln[T[nw].sn[i]]=ln[nw]+1;
G[T[nw].sn[i]]=str;
if(!vis[T[nw].sn[i]]){
vis[T[nw].sn[i]]=1;
q[++tl]=T[nw].sn[i];
}
}if(G[T[nw].sn[i]]<=str) continue;
G[T[nw].sn[i]]=str;
if(!vis[T[nw].sn[i]]){
vis[T[nw].sn[i]]=1;
q[++tl]=T[nw].sn[i];
}
}
}return;
}
void res()
{
SPFA(0);
for(int i=1;i<=n;++i){
f[0][i]=ln[rid[i]];
g[0][i]=G[rid[i]];
}for(int i=1;i<=n;++i){
SPFA(rid[i]);
for(int j=1;j<=n;++j){
f[i][j]=ln[rid[j]];
g[i][j]=G[rid[j]];
}
}return;
}
void slv()
{
memset(I,0x7f,sizeof(I));
for(int i=1;i<=n;++i) I[i][1<<i-1]=f[0][i],H[i][1<<i-1]=g[0][i];
for(int i=1;i<1<<n;++i){
for(int j=1;j<=n;++j){
if((i>>j-1)&1==0) continue;
for(int k=1;k<=n;++k){
if((i>>k-1)&1) continue;
if(I[k][i|(1<<k-1)]<I[j][i]+f[j][k]) continue;
if(I[k][i|(1<<k-1)]>I[j][i]+f[j][k]){
I[k][i|(1<<k-1)]=I[j][i]+f[j][k];
H[k][i|(1<<k-1)]=H[j][i]+g[j][k];
}else if(H[k][i|(1<<k-1)]>H[j][i]+g[j][k]){
H[k][i|(1<<k-1)]=H[j][i]+g[j][k];
}
}
}
}ans=H[1][(1<<n)-1],minn=I[1][(1<<n)-1];
for(int i=2;i<=n;++i){
if(minn>I[i][(1<<n)-1]){
minn=I[i][(1<<n)-1];
ans=H[i][(1<<n)-1];
}else if(minn==I[i][(1<<n)-1]&&ans>H[i][(1<<n)-1]){
ans=H[i][(1<<n)-1];
}
}return;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%s",ch+1),ins(ch,i);
Getfail();res();slv();
cout<<ans<<endl;
return 0;
}
用先进的科学技术与思想文化武装起来的人民,是一个国家最巨大的生产力,是一个社会最强大的推动力,是一个民族最坚实的自信力,是一支军队最可靠的战斗力。
——A·H