题目链接:HDU-5129

题目大意为给一堆字符串,问由任意两个字符串的前缀子串(注意断句)能组成多少种不同的字符串。

思路是先用总方案数减去重复的方案数。

考虑对于一个字符串S,如图,假设S1,S2,S3,S4,S5,S6均为前缀。

换言之,对于这种字符串,我们计算了三次。

发现,重复的方案数,等于中间如图有颜色的方块的数量。所以我们要做的也就是计数像图中有颜色的小方块的数量。

我们可以通过遍历像S6一样的字符串的数量,来计算重复的方案数。S6满足以下条件:

  1. 存在一个前缀S4为S6的后缀,且S4为S6的最长的“是前缀的”后缀(保证是小方块间没有隔板)。
  2. S6-S4为某个前缀的后缀(在图中为S3的后缀)。

我们发现,对于某一个S6,其对应的S4时一定的。

我们用sum[S]表示以S为后缀的前缀字符串的数量。

这样,当我们遍历S6,对于每一个S6,我们找到其对应的S4后,只要减去( sum[S6-S4] - 1 )即可。

所以我们要处理的,就是以下两个问题:

  1. 如何找到S6对应的S4
  2. 如何求sum[S]

这时候,我们发现S6与S4的关系,和AC自动机的性质很像。S6在失配时跳到的位置就是S4。于是第一个问题解决了。

对于第二个问题,我们同样可以通过AC自动机找到。具体的参见代码。

  1. #include<cstring>
  2. #include<cstdio>
  3. #include<queue>
  4. using namespace std;
  5.  
  6. typedef long long LL;
  7. const LL MAXN=;
  8. const LL SIGMA_SIZE=;
  9. struct Trie
  10. {
  11. LL ch[MAXN][SIGMA_SIZE];
  12. LL fa[MAXN];
  13. LL sz; //节点总数
  14. Trie() { sz=; fa[]=-; memset(ch[],,sizeof(ch[])); }
  15. LL idx(char c) { return c-'a'; } //节点c的编号
  16. void clear() { sz=; fa[]=-; memset(ch[],,sizeof(ch[])); }
  17.  
  18. //在Trie中插入字符串s
  19. void insert(char *s)
  20. {
  21. LL u=,n=strlen(s);
  22. for(LL i=;i<n;i++)
  23. {
  24. LL c=idx(s[i]);
  25. if(!ch[u][c]) //节点不存在
  26. {
  27. memset(ch[sz],,sizeof(ch[sz]));
  28. fa[sz]=u;
  29. ch[u][c]=sz++; //新建节点
  30. }
  31. u=ch[u][c]; //往下走
  32. }
  33. }
  34.  
  35. //AC自动机部分
  36. LL f[MAXN];
  37. LL deg[MAXN];
  38. LL sum[MAXN]; //sum[i]表示以Si为后缀的前缀的数量
  39. void getFail()
  40. {
  41. queue<LL> q;
  42. f[]=;
  43. //初始化队列
  44. for(LL c=;c<SIGMA_SIZE;c++)
  45. {
  46. LL u=ch[][c];
  47. if(u) { f[u]=; q.push(u); }
  48. }
  49. //按BFS顺序计算失配函数
  50. while(!q.empty())
  51. {
  52. LL r=q.front(); q.pop();
  53. for(LL c=;c<SIGMA_SIZE;c++)
  54. {
  55. LL u=ch[r][c];
  56. if(!u) { ch[r][c]=ch[f[r]][c]; continue; }
  57. q.push(u);
  58. LL v=f[r];
  59. f[u]=ch[v][c];
  60. }
  61. }
  62. for(LL i=;i<sz;i++) { deg[i]=; sum[i]=; }
  63. for(LL i=;i<sz;i++) deg[f[i]]++;
  64. queue<LL> Q;
  65. for(LL i=;i<sz;i++) if(!deg[i]) Q.push(i);
  66. while(!Q.empty())
  67. {
  68. LL u=Q.front(); Q.pop();
  69. sum[f[u]]+=sum[u];
  70. deg[f[u]]--;
  71. if(!deg[f[u]]) Q.push(f[u]);
  72. }
  73. }
  74.  
  75. void solve()
  76. {
  77. LL tot=;
  78. for(LL i=;i<sz;i++) if(f[i])
  79. {
  80. LL j=f[i];
  81. LL p=i;
  82. while(j)
  83. {
  84. p=fa[p];
  85. j=fa[j];
  86. }
  87. tot+=sum[p]-;
  88. }
  89. printf("%lld\n",1LL*(sz-)*(sz-)-tot);
  90. }
  91. };
  92. Trie T;
  93. int main()
  94. {
  95. #ifdef LOCAL
  96. freopen("in.txt","r",stdin);
  97. #endif
  98. LL n;
  99. while(scanf("%lld",&n) && n)
  100. {
  101. scanf("%lld",&n);
  102. for(LL i=;i<=n;i++)
  103. {
  104. char s[];
  105. scanf("%s",s);
  106. T.insert(s);
  107. }
  108. T.getFail();
  109. T.solve();
  110. T.clear();
  111. }
  112. return ;
  113. }

HDU 5129 Yong Zheng's Death的更多相关文章

  1. 字符串(AC自动机):HDU 5129 Yong Zheng's Death

    Yong Zheng's Death Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/O ...

  2. hdu 5129 (枚举) The E-pang Palace

    题目;http://acm.hdu.edu.cn/showproblem.php?pid=5128. 给你n个点,问能否组成两个不相交的与坐标轴平行的矩形,能就输出两矩形的面积和,不能就输出一个字符串 ...

  3. 2014ACM/ICPC亚洲区广州站题解

    这一场各种计算几何,统统没有做. HDU 5129 Yong Zheng's Death HDU 5136 Yue Fei's Battle

  4. 推荐系统(1)--splitting approaches for context-aware recommendation

    开篇语: 大一的时候.在实验室老师和师兄的带领下.我開始接触推荐系统.时光匆匆,转眼已是大三,因为大三课甚是少.于是便有了时间将自己所学的东西做下总结. 第一篇博客.献给过去三年里带我飞的老师和师兄们 ...

  5. HDU 5860 Death Sequence(死亡序列)

    p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...

  6. HDU 5860 Death Sequence(递推)

    HDU 5860 Death Sequence(递推) 题目链接http://acm.split.hdu.edu.cn/showproblem.php?pid=5860 Description You ...

  7. HDU 6136 Death Podracing(循环链表)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6136 [题目大意] 一堆人在操场上跑步,他们都有一定的速度和初始位置, 当两个人相遇的时候编号较小 ...

  8. 2016 Multi-University Training Contest 10 || hdu 5860 Death Sequence(递推+单线约瑟夫问题)

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5860 题目大意:给你n个人排成一列编号,每次杀第一个人第i×k+1个人一直杀到没的杀.然后 ...

  9. HDU 6136 Death Podracing (堆)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=6136 题解 完了,普及题都不会做了... 发现一个重要性质是只有相邻的人才会相撞,于是直接拿堆维护即可 ...

随机推荐

  1. BZOJ4011 HNOI2015落忆枫音(动态规划+拓扑排序)

    DAG中每个点选一条入边就可以构成一棵有向树,所以如果没有环答案就是∏degreei. 考虑去掉含环的答案.可以看做把环缩点,剩下的点仍然可以任意选入边.于是去除的方案数即为∏degreei/∏deg ...

  2. IntelliJ IDEA2018注册

    第一步:0.0.0.0 account.jetbrains.com及0.0.0.0 www.jetbrains.com  添加到hosts文件 第二步:进入 http://idea.lanyus.co ...

  3. ARC077C pushpush 递推

    ---题面--- 题解: 貌似一般c题都是递推... 观察到最后一个插入的数一定在第一个,倒数第二个插入的数一定在倒数第一个,倒数第三个插入的数一定在第2个,倒数第四个插入的数一定在倒数第2个…… O ...

  4. python安装方法- 3.6.3版本

    一. 官网下载安装包: 官网网址:https://www.python.org/ 我下载的是3.6.3版本,如下图:  二. 安装安装包, 1. 直接双击运行  2. 选择Customize inst ...

  5. POJ2187:Beauty Contest——题解

    http://poj.org/problem?id=2187 题目大意:给n个点,求点对最大距离的平方. ———————————————————— 很容易证明最大距离的点对在最大凸包上. 那么就是旋转 ...

  6. BZOJ1030:[JSOI2007]文本生成器——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=1030 Description JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件 ...

  7. BZOJ1040 骑士 【环套树 树形dp】

    1040: [ZJOI2008]骑士 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 5611  Solved: 2166 [Submit][Stat ...

  8. Spring.NET中事务管理【转】

    http://www.cnblogs.com/GoodHelper/archive/2009/11/16/springnet_transaction.html 浏览了下写的比较清楚. 在.NET FC ...

  9. @Autowired @Resource @Qualifier的区别

    参考博文: http://www.cnblogs.com/happyyang/articles/3553687.html http://blog.csdn.net/revent/article/det ...

  10. Itext2.0.8 和freemarker导出pdf

    这个是跟上一篇写的freemarker导出word是一块的.但是关联性不是很大.由于本人技术有限本篇导出也是根据网上大家的做出的demo混合而成.有不足的地方请大家指出.好改正,使以后看到的freem ...