1. 程式人生 > >BZOJ1195: [HNOI2006]最短母串(Trie圖,搜尋)

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 }