题目传送门


题目描述

JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,
他们现在使用的是GW文本生成器v6版。该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文
章—— 也就是说,生成的文章中每个字节都是完全随机的。如果一篇文章中至少包含使用者们了解的一个单词,
那么我们说这篇文章是可读的(我们称文章a包含单词b,当且仅当单词b是文章a的子串)。但是,即使按照这样的
标准,使用者现在使用的GW文本生成器v6版所生成的文章也是几乎完全不可读的?。ZYX需要指出GW文本生成器 v6
生成的所有文本中可读文本的数量,以便能够成功获得v7更新版。你能帮助他吗?


输入格式

输入文件的第一行包含两个正整数,分别是使用者了解的单词总数N,GW文本生成器v6生成的文本固
定长度M;以下N行,每一行包含一个使用者了解的单词。这里所有单词及文本的长度不会超过100,并且只可能包
含英文大写字母A->Z


输出格式

一个整数,表示可能的文章总数。只需要知道结果模10007的值。


样例

样例输入:

2 2
A
B

样例输出:

100


数据范围与提示

对于全部数据,1≤N≤60,所有单词及文本的长度不会超过100,并且只可能包含英文大写字母。


题解

一看是多模式串,首先应该想到是AC自动机。

如果还不会AC自动机,可以转到这篇博客,个人感觉还是写的挺清楚的:AC自动机讲解+[HDU2222]:Keywords Search(AC自动机)

那么我们考虑怎么去处理。

爆搜的时间复杂度为26m,显然不能接受。

考虑这样一个问题,所有文章的个数减去所有单词能组成的文章的个数即为答案。

考虑使用DP,定义dp[i][j],表示当前点编号为i,已经匹配的长度为j的方案数,注意存储的为所有单词能组成的文章的个数。

dp[i][j]=$\sum$(dp[father][j-1])。

最后用总的文章个数减去$\sum \limits_{i=1}^{cnt}$(dp[i][m])即可。


代码时刻

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int n,m;
  4. char s[101];
  5. int trie[6001][30],cnt=1,ed[6001],nxt[6001];
  6. int dp[6001][101];//dp[i][j]表示当前点编号为i,已经匹配的长度为j的方案数。
  7. int que[6001];
  8. int ans=1;
  9. void insert(char *str)//建树
  10. {
  11. int len=strlen(str);
  12. if(len>m)return;
  13. int p=1;
  14. for(int i=0;i<len;i++)
  15. {
  16. int ch=str[i]-'A';
  17. if(!trie[p][ch])trie[p][ch]=++cnt;
  18. p=trie[p][ch];
  19. }
  20. ed[p]=1;
  21. }
  22. void build()//找Fail指针
  23. {
  24. for(int i=0;i<26;i++)trie[0][i]=1;
  25. que[1]=1;
  26. int head=1,tail=1;
  27. while(head<=tail)
  28. {
  29. for(int i=0;i<26;i++)
  30. {
  31. if(!trie[que[head]][i])trie[que[head]][i]=trie[nxt[que[head]]][i];
  32. else
  33. {
  34. que[++tail]=trie[que[head]][i];
  35. nxt[trie[que[head]][i]]=trie[nxt[que[head]]][i];
  36. ed[trie[que[head]][i]]|=ed[trie[nxt[que[head]]][i]];
  37. }
  38. }
  39. head++;
  40. }
  41. }
  42. void ask()//dp全过程
  43. {
  44. dp[1][0]=1;
  45. for(int i=1;i<=m;i++)
  46. {
  47. for(int j=1;j<=cnt;j++)
  48. {
  49. if(ed[j])continue;
  50. for(int k=0;k<26;k++)
  51. {
  52. if(ed[trie[j][k]])continue;
  53. dp[trie[j][k]][i]=(dp[j][i-1]+dp[trie[j][k]][i])%10007;//转移
  54. }
  55. }
  56. }
  57. for(int i=1;i<=m;i++)ans=(ans*26)%10007;
  58. for(int i=1;i<=cnt;i++)ans=(ans+10007-dp[i][m])%10007;//答案要减去
  59. }
  60. int main()
  61. {
  62. scanf("%d%d",&n,&m);
  63. for(int i=1;i<=n;i++)
  64. {
  65. scanf("%s",s);
  66. insert(s);
  67. }
  68. build();
  69. ask();
  70. cout<<ans;
  71. return 0;
  72. }

rp++

[BZOJ1030]:[JSOI2007]文本生成器(AC自动机+DP)的更多相关文章

  1. [BZOJ1030] [JSOI2007] 文本生成器 (AC自动机 & dp)

    Description JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版.该软件可以随机生成一些文章―――总是 ...

  2. BZOJ1030[JSOI2007]文本生成器——AC自动机+DP

    题目描述 JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版.该软件可以随机生成一些文章―――总是生成一篇长度固 ...

  3. [Bzoj1030][JSOI2007]文本生成器(AC自动机&dp)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1030 最最最常见的多串匹配问题!题目求至少包含一个子串的方案数,则可以转化成全部方案-不 ...

  4. 【bzoj1030】[JSOI2007]文本生成器 AC自动机+dp

    题目描述 JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版.该软件可以随机生成一些文章―――总是生成一篇长度固 ...

  5. 【BZOJ-1030】文本生成器 AC自动机 + DP

    1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3253  Solved: 1330[Submit][Stat ...

  6. [JSOI2007]文本生成器 --- AC自动机 + DP

    [JSOI2007]文本生成器 题目描述: JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版. 该软件可以随机 ...

  7. BZOJ 1030: [JSOI2007]文本生成器 [AC自动机 DP]

    1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3953  Solved: 1614[Submit][Stat ...

  8. 洛谷P4052 [JSOI2007]文本生成器 AC自动机+dp

    正解:AC自动机+dp 解题报告: 传送门! 感觉AC自动机套dp的题还挺套路的,,, 一般就先跑遍AC自动机,然后就用dp dp的状态一般都是f[i][j]:有i个字符,是ac自动机上的第j个节点, ...

  9. [bzoj1030][JSOI2007]文本生成器——AC自动机

    Brief Description 给定一些模式串,您需要求出满足以下要求的字符串的个数. 长度为m 包含任意一个模式串 Algorithm Design 以下内容来自神犇博客 首先运用补集转换,转而 ...

随机推荐

  1. C++中前置操作符和后置操作符的重载

    1,C 语言中讨论了原生含义,C++ 中有必要考虑前置.后置操作符能够重载,有何问题: 2,值得思考的问题: 1,下面的代码有没有区别?为什么? 1,i++  // i 的值作为返回值,i 自增 1: ...

  2. scrapy架构图与执行流程

    概览 本文描述了Scrapy的架构图.数据流动.以及个组件的相互作用 架构图与数据流 上图中各个数字与箭头代表数据的流动方向和流动顺序,具体执行流程如下: 0. Scrapy将会实例化一个Crawle ...

  3. Labeling Balls POJ - 3687 优先队列 + 反向拓扑

    优先队列 + 反向拓扑 //#include<bits/stdc++.h> #include<iostream> #include<cstdio> #include ...

  4. IDEA的快捷方式

    一,IDEA的快捷方式1,F8单步执行 2,F9运行调试 3,CTRL +鼠标左键=进入查看定义 4,CTRL+alt +鼠标左键=查看实现 5,Shift+F6重命名 6,alt +intsert= ...

  5. Mac中如何查看电脑的IP地址

    方法一:使用ifconfig命令 方法二:在charles中查看 Charles 的顶部菜单的 “Help”->”Local IP Address”,即可在弹出的对话框中看到 IP 地址,如下图 ...

  6. laravel5.8 Models

    <?php namespace App\Models; use Illuminate\Notifications\Notifiable;use Illuminate\Contracts\Auth ...

  7. windows核心编程01_错误处理

    windows函数调用出错时,可以通过方法去查询出错根源在哪里. #include <Windows.h> #include <iostream> using namespac ...

  8. linux 读取文本的最后几行

    tail -n 100 filename    读取file的最后100行 tail: n. 尾巴:踪迹:辫子:燕尾服 vt. 尾随:装上尾巴 vi. 跟踪:变少或缩小 adj. 从后面而来的:尾部的 ...

  9. python模块之导入包及模块发布

    1.导入包(不常用的方法) 在使用python的包时,有时候想直接导入包名,然后通过包名来调用模块,例如: temp为我们创建的一个包,如果我们想通过下面的方式进行导入模块中的方法,将会出错 impo ...

  10. etl-p

    java excel 导入数据库 上传文件包  解压导入excel包 导入mysql