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

拿这题练了练数组版的AC自动机

数据范围显然状压 插入时预处理出每个节点是哪个串的结束节点

然后建图 连fail指针的时候合并状态

为了最短显然需要按层转移,所以bfs

可以保证一达到末状态就return得到最优解

数组

  1. #include<queue>
  2. #include<cstdio>
  3. #include<iostream>
  4. #include<cstring>
  5. #include<cstdlib>
  6. using namespace std;
  7. int n,tot=;
  8. char s[];
  9. struct trie
  10. {
  11. int son[],st,fail;
  12. }t[];
  13. void ins(char* str,int k)
  14. {
  15. int l=strlen(str+),root=;
  16. for(int i=;i<=l;i++)
  17. {
  18. int x=str[i]-'A';
  19. if(!t[root].son[x])t[root].son[x]=++tot;
  20. root=t[root].son[x];
  21. }
  22. t[root].st|=<<(k-);
  23. }
  24. void build()
  25. {
  26. queue<int> q;
  27. for(int i=;i<;i++)
  28. if(t[].son[i])q.push(t[].son[i]);
  29. while(!q.empty())
  30. {
  31. int x=q.front();
  32. q.pop();
  33. for(int i=;i<;i++)
  34. {
  35. int &y=t[x].son[i];
  36. if(!y)
  37. {
  38. y=t[t[x].fail].son[i];
  39. continue;
  40. }
  41. t[y].fail=t[t[x].fail].son[i];
  42. t[y].st|=t[t[y].fail].st;
  43. q.push(y);
  44. }
  45. }
  46. }
  47. bool v[][(<<)+];
  48. int let[(<<)+],fa[(<<)+],ans[],num=;
  49. void bfs()
  50. {
  51. queue<pair<int,int> > q;
  52. q.push(make_pair(,));
  53. int f=,ss=;
  54. while(!q.empty())
  55. {
  56. int x=q.front().first,nowst=q.front().second;
  57. q.pop();
  58. if(nowst==(<<n)-)
  59. {
  60. for(int i=f;i;i=fa[i])
  61. ans[++num]=let[i];
  62. for(int i=num;i;i--)putchar(ans[i]+'A');
  63. return ;
  64. }
  65. for(int i=;i<;i++)
  66. {
  67. int y=t[x].son[i],nxtst=nowst|t[y].st;
  68. if(!v[y][nxtst])
  69. {
  70. v[y][nxtst]=;
  71. ss++;
  72. fa[ss]=f;
  73. let[ss]=i;
  74. q.push(make_pair(y,nxtst));
  75. }
  76. }
  77. f++;
  78. }
  79. }
  80. int main()
  81. {
  82. scanf("%d",&n);
  83. for(int i=;i<=n;i++)
  84. {
  85. scanf("%s",s+);
  86. ins(s,i);
  87. }
  88. build();
  89. bfs();
  90. return ;
  91. }

指针

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<queue>
  5. #include<cstdlib>
  6. using namespace std;
  7. const int N=;
  8. int n;
  9. char s[N];
  10. struct node
  11. {
  12. node *son[];
  13. int st;
  14. bool vis[(<<)+];
  15. node *fail;
  16. node()
  17. {
  18. memset(this,,sizeof(node));
  19. }
  20. };
  21. node *root;
  22. void ini()
  23. {
  24. root=new node();
  25. }
  26. void ins(char *str,int num)
  27. {
  28. int l=strlen(str+);
  29. node *now=root;
  30. for(int i=;i<=l;i++)
  31. {
  32. if(!now->son[str[i]-'A'])now->son[str[i]-'A']=new node();
  33. now=now->son[str[i]-'A'];
  34. }
  35. now->st|=<<(num-);
  36. }
  37.  
  38. void build()
  39. {
  40. queue<node*>q;
  41. for(int i=;i<;i++)
  42. {
  43. if(root->son[i])
  44. {
  45. root->son[i]->fail=root;
  46. q.push(root->son[i]);
  47. }
  48. else root->son[i]=root;
  49. }
  50. while(!q.empty())
  51. {
  52. node *x=q.front();
  53. q.pop();
  54. for(int i=;i<;i++)
  55. {
  56. if(x->son[i])
  57. {
  58. x->son[i]->fail=x->fail->son[i];
  59. if(x->son[i]->fail)x->son[i]->st|=x->son[i]->fail->st;
  60. q.push(x->son[i]);
  61. }
  62. else x->son[i]=x->fail->son[i];
  63. }
  64. }
  65. }
  66. int fa[],ans[],tot=,qwq[];
  67. void bfs()
  68. {
  69. queue<node*> q;
  70. queue<int> ST;
  71. q.push(root);ST.push();
  72. root->vis[]=;
  73. int f=,ss=;
  74. while(!q.empty())
  75. {
  76. node *x=q.front();int nowSt=ST.front();
  77. q.pop();ST.pop();
  78. // cout<<(x->st)<<endl;
  79. if(nowSt==(<<n)-)
  80. {
  81. for(int i=f;i;i=fa[i])ans[++tot]=qwq[i];
  82. for(int i=tot;i;i--)putchar(ans[i]+'A');
  83. return ;
  84. }
  85. for(int i=;i<;i++)
  86. {
  87. if(!x->son[i])continue;
  88. int state=nowSt|(x->son[i]->st);
  89. if(!x->son[i]->vis[state])
  90. {
  91. x->son[i]->vis[state]=;
  92. ss++;
  93. fa[ss]=f;
  94. qwq[ss]=i;
  95. q.push(x->son[i]);
  96. ST.push(state);
  97. }
  98. }
  99. f++;
  100. }
  101. }
  102. int main()
  103. {
  104. scanf("%d",&n);
  105. ini();
  106. for(int i=;i<=n;i++)
  107. {
  108. scanf("%s",s+);
  109. ins(s,i);
  110. }
  111. build();
  112. bfs();
  113. return ;
  114. }

(话说这题数组大小神TM坑啊……)

[HNOI2006]最短母串 (AC自动机+状压)的更多相关文章

  1. bzoj1195 [HNOI2006]最短母串 AC 自动机+状压+bfs

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=1195 题解 建立 AC 自动机,然后构建出 trie 图. 然后直接在 trie 图上走.但是 ...

  2. BZOJ 1195: [HNOI2006]最短母串 AC自动机+状压+搜索

    思路比较直接. 由于 $n$ 很小,直接定义 $f[i][j]$ 表示当前在自动机中的节点 $i,$ 被覆盖串的集合为 $j$ 的方案数. #include <bits/stdc++.h> ...

  3. 【bzoj1195】[HNOI2006]最短母串 AC自动机+状态压缩+BFS最短路

    原文地址:http://www.cnblogs.com/GXZlegend/p/6825226.html 题目描述 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串 ...

  4. BZOJ1195[HNOI2006]最短母串——AC自动机+BFS+状态压缩

    题目描述 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串. 输入 第一行是一个正整数n(n<=12),表示给定的字符串的 ...

  5. Bzoj1195 [HNOI2006]最短母串 [AC自动机]

    Time Limit: 10 Sec  Memory Limit: 32 MBSubmit: 1304  Solved: 439 Description 给定n个字符串(S1,S2,„,Sn),要求找 ...

  6. BZOJ 1195 [HNOI2006]最短母串 (Trie图+状压+bfs最短路)

    BZOJ1195 LOJ10061 题目大意:给你$n$个模式串,求一个最短且字典序最小的文本串并输出这个串,$n<=12,len<=50$ 首先对所有模式串构造$Trie$图,$Trie ...

  7. BZOJ1195 [HNOI2006]最短母串 AC自动机 bfs

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 传送门 - BZOJ1195 题意概括 给出一堆串,然后求一个包含这些串的所有串的最短的中的字典序最小的. 题解 先造一个AC ...

  8. BZOJ_1195_[HNOI2006]最短母串_AC自动机+BFS+分层图

    BZOJ_1195_[HNOI2006]最短母串_AC自动机+BFS+分层图 Description 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2, ...

  9. 【状态压缩dp】1195: [HNOI2006]最短母串

    一个清晰的思路就是状压dp:不过也有AC自动机+BFS的做法 Description 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T ...

随机推荐

  1. js location对象相关命令

    Location.href 返回整个当前url,若对其赋值:location.href="http://www.sina.com.cn"则跳转其urllocation.host 返 ...

  2. swift 笔记 (二十一) —— 高级运算符

    高级运算符 位运算符 按位取反: ~ 按位与运算:  & 按位或运算:  | 按位异或运算:  ^ 按位左移运算: << 按位右移动算: >> 溢出运算符 自从swif ...

  3. 远程查看日志-linux

    ssh 连接服务器 ssh user@www.xxx.com -p60022 用户名@ip 端口 进入日志所在目录 cat FILENAME 查看文本文件,P.S. 在查较大文件时为了避免刷屏,请使用 ...

  4. C#中,JSON字符串转换成对象。

    在前台提交(post)的数据中.除了强类型的数据外,还有一个额外的json数据提交 在这里我的办法是,在前台把json对象转换成字符串,然后提交. 测试demo 前台: @using(Html.Beg ...

  5. YTU 2500: 二元表达式计算

    2500: 二元表达式计算 时间限制: 1 Sec  内存限制: 128 MB 提交: 38  解决: 23 题目描述 根据输入的含有两个二元运算的表达式,编程计算并输出表达式的值.如输入:  2+9 ...

  6. memcached知识点梳理

    Memcached概念:    Memcached是一个免费开源的,高性能的,具有分布式对象的缓存系统,它可以用来保存一些经常存取的对象或数据,保存的数据像一张巨大的HASH表,该表以Key-valu ...

  7. 开源框架 KJFrameForAndroid

    一个Android的快速开发工具包,使用它你可以轻松实现网络请求.插件化开发.图片加载等功能.KJFrameForAndroid的设计思想是通过封装Android原生SDK中复杂的复杂操作而达到简化A ...

  8. 不温不火WindowsPhone

    最近在考虑是否转其他平台,如iOS或者Android或者javascript等. 已经以Windows Phone 开发作为工作就一年了(也不算是真正的Windows Phone开发吧,仅仅是开发高德 ...

  9. clc和clear命令的使用

    clc命令是用来清除命令窗口的内容,这点不用多说.不管开启多少个应用程序,命令窗口只有一个,所以clc无论是在脚本m文件或者函数m文件调用时,clc命令都会清除命令窗口的内容.clear命令可以用来清 ...

  10. LVS的持久连接、会话保持和高可用介绍

    持续连接 1)持久连接(lvs persistence)模板: 实现无论使用任何调度算法,在一段时间内(默认360s),能够实现将来自同一个地址的请求始终发往同一个RS ipvsadm -A|E -t ...