辣鸡OI毁我青春

Description

The alphabet of Freeland consists of exactly N letters. Each sentence of Freeland language (also known as Freish) consists of exactly M letters without word breaks. So, there exist exactly N^M different Freish sentences.

But after recent election of Mr. Grass Jr. as Freeland president
some words offending him were declared unprintable and all sentences
containing at least one of them were forbidden. The sentence S contains a
word W if W is a substring of S i.e. exists such k >= 1 that S[k] =
W[1], S[k+1] = W[2], ...,S[k+len(W)-1] = W[len(W)], where k+len(W)-1
<= M and len(W) denotes length of W. Everyone who uses a forbidden
sentence is to be put to jail for 10 years.

Find out how many different sentences can be used now by freelanders without risk to be put to jail for using it.

Input

The
first line of the input file contains three integer numbers: N -- the
number of letters in Freish alphabet, M -- the length of all Freish
sentences and P -- the number of forbidden words (1 <= N <= 50, 1
<= M <= 50, 0 <= P <= 10).

The second line contains exactly N different characters -- the
letters of the Freish alphabet (all with ASCII code greater than 32).

The following P lines contain forbidden words, each not longer than
min(M, 10) characters, all containing only letters of Freish alphabet.

Output

Output the only integer number -- the number of different sentences freelanders can safely use.

Sample Input

  1. 2 3 1
  2. ab
  3. bb

Sample Output

  1. 5

Source

Northeastern Europe 2001, Northern Subregion

把P串建成AC自动机,在trie树上动规。f[i][j]表示字符串长度为i,目前走到ac自动机的j结点时的可行方案数。

循环i,j,枚举尝试j可到的下一个结点k,若自动机上k结点不是终止结点,则可以转移:f[i+1][k]+=f[i][j]

P串中可能会出现一个包含另一个的情况。处理方法:在建树时,若fail[x]是终止结点,x也标记成终止结点。

加了个map映射来缩小树规模,其实直接用普通int数组映射也行

  1. #include<iostream>
  2. #include<algorithm>
  3. #include<cstdio>
  4. #include<cmath>
  5. #include<cstring>
  6. #include<queue>
  7. #include<map>
  8. using namespace std;
  9. int n,m,p;
  10. char alpha[];
  11. map<char,int> mp;
  12. struct num
  13. {
  14. int l,a[];
  15. num operator + (const num &x) const
  16. {
  17. num ans;
  18. int len;
  19. memset(ans.a,,sizeof(ans.a));
  20. for (int i=;i<=l||i<=x.l;i++)
  21. {
  22. ans.a[i]+=a[i]+x.a[i];
  23. ans.a[i+]+=ans.a[i]/;
  24. ans.a[i]%=;
  25. }
  26. if (l<x.l) len=x.l+;
  27. else len=l+;
  28. while (!ans.a[len]&&len) len--;
  29. ans.l=len;
  30. return ans;
  31. }
  32. }f[][],ans;
  33. void prt(num x)
  34. {
  35. printf("%d",x.a[x.l]);
  36. for (int i=x.l-;i>=;i--)
  37. {
  38. int y=x.a[i];
  39. if (y<) printf("");
  40. if (y<) printf("");
  41. if (y<) printf("");
  42. printf("%d",y);
  43. }
  44. }
  45. struct ACa
  46. {
  47. int next[][];
  48. int fail[],end[];
  49. int root,cnt;//根结点,计数器
  50. int newnode(){
  51. for(int i=;i<n;i++){
  52. next[cnt][i]=-;//子结点设为空
  53. }
  54. end[cnt++]=;//以该结点结束的串数
  55. return cnt-;
  56. }
  57. void clear(){//初始化
  58. cnt=;//结点数重置
  59. root=newnode();//初始化根结点 //完成后root=0
  60. }
  61. void insert(char c[]){
  62. int now=root;
  63. int len=strlen(c);
  64. for(int i=;i<len;i++){
  65. if(next[now][mp[c[i]]]==-)//如果对应结点未建立,添加结点
  66. next[now][mp[c[i]]]=newnode();
  67. now=next[now][mp[c[i]]];//否则沿结点继续
  68. }
  69. end[now]++;
  70. }
  71. void build(){
  72. queue<int>q;
  73. fail[root]=root;
  74. for(int i=;i<n;i++){
  75. if(next[root][i]==-)
  76. next[root][i]=root;
  77. else{//有结点则入队
  78. fail[next[root][i]]=root;
  79. q.push(next[root][i]);
  80. }
  81. end[next[root][i]]|=end[next[root][i]];
  82. }
  83. while(!q.empty())
  84. {
  85. int now=q.front();
  86. q.pop();
  87. end[now]|=end[fail[now]];
  88. for(int i=;i<n;i++){
  89. if(next[now][i]==-)
  90. next[now][i]=next[fail[now]][i];//链接到fail指针对应结点的后面
  91. else{
  92. fail[next[now][i]]=next[fail[now]][i];
  93. q.push(next[now][i]);
  94. }
  95. }
  96. }
  97. return;
  98. }
  99. };
  100. ACa ac;
  101. int main(){
  102. scanf("%d%d%d\n",&n,&m,&p);
  103. int i,j;int k;
  104. scanf("%s",alpha);
  105. for(i=;i<n;i++)mp[alpha[i]]=i;//
  106. char c[];
  107. ac.clear();
  108. for(i=;i<=p;i++){
  109. scanf("%s",c);
  110. ac.insert(c);
  111. }
  112. ac.build();
  113. f[][].l=;
  114. f[][].a[]=;
  115. for(i=;i<m;i++){//字符串长度
  116. for(j=;j<ac.cnt;j++)//ac自动机的结点
  117. for(k=;k<n;k++){
  118. int to=ac.next[j][k];//下一步尝试到达的结点
  119. if(ac.end[to])continue;
  120. f[i+][to]=f[i+][to]+f[i][j];
  121. }
  122. }
  123. for(i=;i<ac.cnt;i++)if(!ac.end[i])ans=ans+f[m][i];
  124. prt(ans);
  125. return ;
  126. }

POJ 1625 Censored!的更多相关文章

  1. POJ 1625 Censored!(AC自动机+DP+高精度)

    Censored! Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 6956   Accepted: 1887 Descrip ...

  2. POJ 1625 Censored!(AC自动机+高精度+dp)

    http://poj.org/problem?id=1625 题意: 给出一些单词,求长度为m的串不包含这些单词的个数. 思路: 这道题和HDU 2243和POJ 2778是一样的,不同的是这道题不取 ...

  3. POJ 1625 Censored! [AC自动机 高精度]

    Censored! Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 9793   Accepted: 2686 Descrip ...

  4. POJ 1625 Censored! (AC自己主动机 + 高精度 + DP)

    题目链接:Censored! 解析:AC自己主动机 + 高精度 + 简单DP. 字符有可能会超过128.用map映射一下就可以. 中间的数太大.得上高精度. 用矩阵高速幂会超时,简单的DP就能解决时间 ...

  5. POJ 1625 Censored ( Trie图 && DP && 高精度 )

    题意 : 给出 n 个单词组成的字符集 以及 p 个非法串,问你用字符集里面的单词构造长度为 m 的单词的方案数有多少种? 分析 :先构造出 Trie 图方便进行状态转移,这与在 POJ 2278 中 ...

  6. POJ 1625 Censored!(大数+DP)

    题目链接 这题,真心木啥意思,就是数据里貌似字符有负数,注意gets读入.. #include <iostream> #include <cstring> #include & ...

  7. POJ 1625 Censored!(AC自动机->指针版+DP+大数)题解

    题目:给你n个字母,p个模式串,要你写一个长度为m的串,要求这个串不能包含模式串,问你这样的串最多能写几个 思路:dp+AC自动机应该能看出来,万万没想到这题还要加大数...orz 状态转移方程dp[ ...

  8. POJ 1625 Censored!(AC自动机 + DP + 大数 + 拓展ASCII处理)题解

    题意:给出n个字符,p个病毒串,要你求出长度为m的不包含病毒串的主串的个数 思路:不给取模最恶劣情况$50^{50}$,所以用高精度板子.因为m比较小,可以直接用DP写. 因为给你的串的字符包含拓展A ...

  9. Match:Censored!(AC自动机+DP+高精度)(POJ 1625)

     Censored! 题目大意:给定一些字符,将这些字符组成一个固定长度的字符串,但是字符串不能包含一些禁词,问你有多少种组合方式. 这是一道好题,既然出现了“一些”禁词,那么这题肯定和AC自动机有点 ...

随机推荐

  1. ClickJacking(点击劫持)

    问题: 点击劫持(ClickJacking)是一种视觉上的欺骗手段.大概有两种方式,一是攻击者使用一个透明的iframe,覆盖在一个网页上,然后诱使用户在该页面上进行操作,此时用户将在不知情的情况下点 ...

  2. android 中打 Log 的一些技巧

    在 android 平台上搞开发工作,会经常用到一些 Log 输出调试信息. 众所周知,android 中有五种类型的 Log , v, d, i, w, e 这里就不再赘 述 (如果对这些不了解的朋 ...

  3. SpringMVC中的@PathVariable

    @PathVariable是用来动态获得url中的参数的,代码示例如下: 可以在代码中获得lev_1.lev_2和target参数的值看一下 // 支持跳转到WEB-INF/目录下二层目录 @Requ ...

  4. OAF与XML Publisher集成(转)

    原文地址:OAF与XML Publisher集成 有两种方式,一种是用VO与XML Publisher集成,另一种是用PL/SQL与XML Publisher集成 用VO与XML Publisher集 ...

  5. Android开发环境搭建及常见问题解决方法

    转自: http://www.cnblogs.com/rwxwsblog/p/4769785.html 在移动互联网的时代,Android的份额早已超过了苹果.Android的出现无疑加速了移动互联网 ...

  6. LeetCode-Group Shifted Strings

    Given a string, we can "shift" each of its letter to its successive letter, for example: & ...

  7. 实验二实验报告 20135324&&20135330

    北京电子科技学院(BESTI) 实 验 报 告 课程: 深入理解计算机系统 班级: 1353 姓名: 杨舒雯 张若嘉 学号: 20135324 20135330 成绩: 指导教师: 娄嘉鹏 实验日期: ...

  8. clip to bounds 和mask to bounds的区别

    UIView.clipsToBounds 让子 View 只显示落在父 View 的 Frame 部分:是子视图超出不现实,默认为NO,设置为YES就会把超出的部分裁掉. maskToBounds 是 ...

  9. Opencv step by step - 配置文件

    有时候,我们需要用配置文件存储一些图像或者视频的信息. 先来一个简单的例子: #include <cv.h> #include <highgui.h> int main(int ...

  10. Object C学习笔记18-SEL,@ selector,Class,@class

    本章是对上一章<<Object C学习笔记17-动态判断和选择器>>的一点补充,所以比较简单点. 一. SEL 类型 在上一篇介绍了几个方法,都只是介绍了其使用方式但是没有具体 ...