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
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 }