题解 [HNOI2006]最短母串问题

题意:给出n个字符串,求一个最短的串使得所有字符串都是这个串的子串。

先把字符串建出 AC 自动机,问题等价于求一条最小的链,使得这个连经过每个串的结尾。链上的字符即为所求字符串。
所以我们bfs,因为n12所以判断到没到过这个串的结尾可以用二进制,0表示没有到过,1表示到过。设置到结尾时用按位或|运算。
最后答案就是第一次状态每一位都为1所记录的字符串。

代码

Copy
#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); }
posted @   CelticOIer  阅读(99)  评论(1编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示