[BZOJ1195]最短母串

1195: [HNOI2006]最短母串

Time Limit: 10 Sec  Memory Limit: 32 MB

Description

给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串。

Input

第一行是一个正整数n(n<=12),表示给定的字符串的个数。以下的n行,每行有一个全由大写字母组成的字符串。每个字符串的长度不超过50.

Output

只有一行,为找到的最短的字符串T。在保证最短的前提下,如果有多个字符串都满足要求,那么必须输出按字典序排列的第一个。

Sample Input

2
ABCD
BCDABC

Sample Output

ABCDABC
 
题解:
一开始的确想到了状压……但是没有想到后面的操作……
而且这个题让我不得不打数组版……痛心疾首。
如果我们按照AC自动机来做这道题,我们可以这样考虑:
建好trie图之后,从根节点跑一个BFS最短路,并且按照A~Z的顺序往下走,
那么我们就实现了“最短”和“字典序最小”。
而对于字符串,我们可以用状压来记录每个串是否出现。
代码见下:
 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 const int K=1<<12;
 5 const int N=610;
 6 short n,cnt,bit[20];
 7 char s[15][60],ans[N],c[N*K];
 8 short val[N],ch[N][26],f[N];
 9 bool vis[N][K];
10 int from[N*K],q[N],hd,tl;
11 short state[N*K],point[N*K];
12 inline void get_fail()
13 {
14     hd=0,tl=0;
15     for(int i=0;i<26;i++)
16         if(ch[0][i])q[tl++]=ch[0][i];
17     while(hd^tl)
18     {
19         int rt=q[hd++];
20         for(int i=0;i<26;i++)
21         {
22             int u=f[rt];
23             if(ch[rt][i])
24             {
25                 q[tl++]=ch[rt][i];
26                 while(u&&!ch[u][i])u=f[u];
27                 f[ch[rt][i]]=ch[u][i];
28                 val[ch[rt][i]]|=val[ch[u][i]];
29             }
30             else
31                 ch[rt][i]=ch[u][i];
32         }
33     }
34 }
35 inline void get_ans()
36 {
37     hd=0,tl=1;
38     while(hd^tl)
39     {
40         int u=point[hd],st=state[hd];
41         if(st==bit[n]-1)
42         {
43             int id=0;
44             while(hd)ans[++id]=c[hd],hd=from[hd];
45             while(id>=1)putchar(ans[id]),id--;
46             return;
47         }
48         for(int i=0;i<26;i++)
49         {
50             if(!vis[ch[u][i]][st|val[ch[u][i]]])
51             {
52                 point[tl]=ch[u][i];
53                 c[tl]=i+'A',from[tl]=hd;
54                 state[tl]=st|val[ch[u][i]];
55                 vis[point[tl]][state[tl]]=1;
56                 tl++;
57             }
58         }
59         hd++;
60     }
61 }
62 int main()
63 {
64     scanf("%d",&n);
65     bit[0]=1;for(int i=1;i<=n;i++)bit[i]=bit[i-1]<<1;
66     for(int i=1;i<=n;i++)
67     {
68         scanf("%s",s[i]);
69         int rt=0;int m=strlen(s[i]);
70         for(int j=0;j<m;j++)
71         {
72             int d=s[i][j]-'A';
73             if(!ch[rt][d])ch[rt][d]=++cnt;
74             rt=ch[rt][d];
75         }
76         val[rt]|=bit[i-1];
77     }
78     get_fail();get_ans();
79 }
[BZOJ1195]
posted @ 2017-07-02 19:25  LadyLex  阅读(374)  评论(0编辑  收藏  举报