題解 [HNOI2006]最短母串問題
阿新 • • 發佈:2020-09-08
題意:給出\(n\)個字串,求一個最短的串使得所有字串都是這個串的子串。
先把字串建出 AC 自動機,問題等價於求一條最小的鏈,使得這個連經過每個串的結尾。鏈上的字元即為所求字串。
所以我們\(bfs\),因為\(n\leq 12\)所以判斷到沒到過這個串的結尾可以用二進位制,\(0\)表示沒有到過,\(1\)表示到過。設定到結尾時用按位或\(\,|\,\)運算。
最後答案就是第一次狀態每一位都為\(1\)所記錄的字串。
程式碼
#include<bits/stdc++.h> #define eps 1e-7 #define re register #define N 3001001 #define MAX 5001 #define inf 1e18 using namespace std; typedef int ll; typedef double db; inline void read(re ll& ret) { ret=0;re ll pd=0;re char c=getchar(); while(!isdigit(c)){pd|=c=='-';c=getchar();} while(isdigit(c)){ret=(ret<<1)+(ret<<3)+(c^48);c=getchar();} ret=pd?-ret:ret; } ll n,trie[601][26],tot,f[MAX],nxt[MAX]; char s[MAX]; inline void insert(re ll pos) { re ll p=0,len=strlen(s+1); for(re int i=1;i<=len;i++) { re ll c=s[i]-'A'; if(!trie[p][c]) trie[p][c]=++tot; p=trie[p][c]; } f[p]|=(1<<pos); } ll b[MAX],sum; inline void bfs() { queue<ll>q; for(re int i=0;i<26;i++) if(trie[0][i]) q.push(trie[0][i]); while(!q.empty()) { re ll p=q.front(); b[++sum]=p; q.pop(); for(re int i=0;i<26;i++) { if(!trie[p][i]) trie[p][i]=trie[nxt[p]][i]; else { nxt[trie[p][i]]=trie[nxt[p]][i]; q.push(trie[p][i]); } } } } struct node { ll p,state,fa,data; char c; }ans[1350000]; queue<node>q; bool vis[601][MAX]; ll top; int main() { read(n); for(re int i=1;i<=n;i++) { scanf("%s",s+1); insert(i); } bfs(); for(re int i=sum;i;i--) f[i]|=f[nxt[i]]; re node qwq; qwq.p=0; qwq.state=f[0]; qwq.fa=0; qwq.c=0; qwq.data=++top; ans[top]=qwq; q.push(qwq); while(!q.empty()) { // if(top>1000000) // cout<<top<<endl; qwq=q.front(); q.pop(); /* re node tt=qwq; re ll cnt=0; while(qwq.fa) { s[++cnt]=qwq.c; qwq=ans[qwq.fa]; } for(re int i=cnt;i;i--) putchar(s[i]); putchar('\n'); qwq=tt;*/ // cout<<qwq.p<<" "<<qwq.data<<" "<<qwq.state<<" "<<qwq.fa<<endl; if(qwq.state+2==(1<<n+1)) { re ll cnt=0; while(qwq.fa) { s[++cnt]=qwq.c; qwq=ans[qwq.fa]; } for(re int i=cnt;i;i--) putchar(s[i]); putchar('\n'); break; } re ll tmp=qwq.p; re node qaq; for(re int i=0;i<26;i++) if(trie[qwq.p][i]) { qaq.p=trie[qwq.p][i]; qaq.state=(qwq.state|f[qaq.p]); if(vis[qaq.p][qaq.state]) continue; qaq.c=char(i+'A'); // cout<<qaq.c<<endl; qaq.fa=qwq.data; qaq.data=++top; ans[top]=qaq; // cout<<qaq.p<<" "<<qaq.data<<" "<<qaq.state<<" "<<qaq.fa<<endl; vis[qaq.p][qaq.state]=true; q.push(qaq); } } exit(0); }