BZOJ1195: [HNOI2006]最短母串(Trie图,搜索)

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

解题思路:

最优解还是要Bfs的,状态这么少。

防止其空间爆炸,采用路径记录法。

状态为两部分:自动机上节点编号及终止子串个数。

想开二维数组存状态,但是已知后面状态的上限,取模和除操作即为压缩。

代码:

  1 #include<queue>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 struct trnt{
  6     int ch[26];
  7     int fl;
  8     int fin;
  9 }tr[700];
 10 int siz;
 11 int n,m;
 12 int lim;
 13 int oo;
 14 int ans[2000000];
 15 int lst[2000000];
 16 int val[2000000];
 17 char tmp[100];
 18 std::queue<int>Q,S;
 19 int zip(int plc,int sit){return plc*oo+sit;}
 20 int Plc(int bag){return bag/oo;}
 21 int Sit(int bag){return bag%oo;}
 22 void Insert(char *a,int t)
 23 {
 24     int root=0;
 25     int len=strlen(a+1);
 26     for(int i=1;i<=len;i++)
 27     {
 28         int c=a[i]-'A';
 29         if(!tr[root].ch[c])
 30             tr[root].ch[c]=++siz;
 31         root=tr[root].ch[c];
 32     }
 33     tr[root].fin|=(1<<(t-1));
 34     return ;
 35 }
 36 void Build(void)
 37 {
 38     int root=0;
 39     for(int i=0;i<26;i++)
 40         if(tr[root].ch[i])
 41             Q.push(tr[root].ch[i]);
 42     while(!Q.empty())
 43     {
 44         root=Q.front();
 45         Q.pop();
 46         tr[root].fin|=tr[tr[root].fl].fin;
 47         for(int i=0;i<26;i++)
 48         {
 49             if(tr[root].ch[i])
 50             {
 51                 tr[tr[root].ch[i]].fl=tr[tr[root].fl].ch[i];
 52                 Q.push(tr[root].ch[i]);
 53             }else
 54                 tr[root].ch[i]=tr[tr[root].fl].ch[i];
 55         }
 56     }
 57     return ;
 58 }
 59 void Bfs(void)
 60 {
 61     memset(lst,-1,sizeof(lst));
 62     lst[0]=-2;
 63     S.push(0);
 64     while(!S.empty())
 65     {
 66         int B=S.front();
 67         S.pop();
 68         int root=Plc(B);
 69         int situ=Sit(B);
 70         if(situ==oo-1)
 71         {
 72             
 73             while(lst[B]!=-2)
 74             {
 75                 
 76                 ans[++lim]=val[B];
 77                 B=lst[B];
 78             }
 79             for(int i=lim;i;i--)
 80                 putchar(ans[i]+'A');
 81             puts("");
 82             return ;
 83         }
 84         for(int i=0;i<26;i++)
 85         {
 86             
 87             int nwrt=tr[root].ch[i];
 88             int nwst=situ|tr[nwrt].fin;
 89             int nwB=zip(nwrt,nwst);
 90             if(~lst[nwB])
 91                 continue;
 92             lst[nwB]=B;
 93             val[nwB]=i;
 94             S.push(nwB);
 95         }
 96     }
 97     return ;
 98 }
 99 int main()
100 {
101     //freopen("tmp.in","r",stdin);
102     scanf("%d",&n);    oo=1<<n;
103     for(int i=1;i<=n;i++)
104     {
105         scanf("%s",tmp+1);
106         Insert(tmp,i);
107     }
108     Build();
109     Bfs();
110     return 0;
111 }

猜你喜欢

转载自www.cnblogs.com/blog-Dr-J/p/10014032.html
今日推荐