辣鸡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

2 3 1
ab
bb

Sample Output

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[60];
 11 map<char,int> mp;
 12 struct num
 13 {
 14     int l,a[100];
 15     num operator + (const num &x) const
 16     {
 17         num ans;
 18         int len;
 19         memset(ans.a,0,sizeof(ans.a));
 20         for (int i=1;i<=l||i<=x.l;i++)
 21         {
 22             ans.a[i]+=a[i]+x.a[i];
 23             ans.a[i+1]+=ans.a[i]/10000;
 24             ans.a[i]%=10000;
 25         }
 26         if (l<x.l) len=x.l+1;
 27         else len=l+1;
 28         while (!ans.a[len]&&len) len--;
 29         ans.l=len;
 30         return ans;
 31     }
 32 }f[110][110],ans;
 33 void prt(num x)
 34 {
 35     printf("%d",x.a[x.l]);
 36     for (int i=x.l-1;i>=1;i--)
 37     {
 38         int y=x.a[i];
 39         if (y<1000) printf("0");
 40         if (y<100) printf("0");
 41         if (y<10) printf("0");
 42         printf("%d",y);
 43     }
 44 }
 45 struct ACa
 46 {
 47     int next[500][100];
 48     int fail[500],end[500];
 49     int root,cnt;//根结点,计数器
 50     int newnode(){
 51         for(int i=0;i<n;i++){
 52             next[cnt][i]=-1;//子结点设为空
 53         }
 54         end[cnt++]=0;//以该结点结束的串数
 55         return cnt-1;
 56     }
 57     void clear(){//初始化
 58         cnt=0;//结点数重置
 59         root=newnode();//初始化根结点 //完成后root=0
 60     }
 61     void insert(char c[]){
 62         int now=root;
 63         int len=strlen(c);
 64         for(int i=0;i<len;i++){
 65             if(next[now][mp[c[i]]]==-1)//如果对应结点未建立,添加结点
 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=0;i<n;i++){
 75             if(next[root][i]==-1)
 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=0;i<n;i++){
 89                 if(next[now][i]==-1)
 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=0;i<n;i++)mp[alpha[i]]=i;//
106     char c[60];
107     ac.clear();
108     for(i=1;i<=p;i++){
109         scanf("%s",c);
110         ac.insert(c);
111     }
112     ac.build();
113     f[0][0].l=1;
114     f[0][0].a[1]=1;
115     for(i=0;i<m;i++){//字符串长度
116         for(j=0;j<ac.cnt;j++)//ac自动机的结点
117             for(k=0;k<n;k++){
118                 int to=ac.next[j][k];//下一步尝试到达的结点
119                 if(ac.end[to])continue;
120                     f[i+1][to]=f[i+1][to]+f[i][j];
121             }
122     }
123     for(i=0;i<ac.cnt;i++)if(!ac.end[i])ans=ans+f[m][i];
124     prt(ans);
125     return 0;
126 }

转载于:https://www.cnblogs.com/SilverNebula/p/5644170.html

POJ 1625 Censored!相关推荐

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

    链接 POJ 1625 题意 给出P个模式串,问长度为M且不含有P中任何一个为子串的字符串有多少种. 给出了大小为N的一个字符集,属于ASCII但不一定为英文字母. 最终答案不进行取模,所以可能非常大 ...

  2. POJ - 1625 Censored!

    希望自己能成为日更博主 题目连接:http://poj.org/problem?id=1625  题目大意:给你n个字母,再给你p个字符串,问有多少个长度为m的只由给出的n个字母构成的字符串,且字符串 ...

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

    题意 : 给出 n 个单词组成的字符集 以及 p 个非法串,问你用字符集里面的单词构造长度为 m 的单词的方案数有多少种? 分析 : 与 POJ 2778 非常相似的一道题目,如果没有做过就尝试去了解 ...

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

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

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

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

  6. POJ 1625 Censored!

    给定p个模式串,求长度为m<=50的串中不包含任何模式串的串的种类数,字符仅由给出的n个字符构成,用mp数组标记下.然后和之前的几道类似,利用end和next数组得到转态转移数组,然后由于题目数 ...

  7. POJ - 1625 Censored!(AC自动机+dp+高精度运算)

    题目链接:点击查看 题目大意:给出一个含有 n 个不同字符的字符集,接着规定所有单词的长度为 m ,再给出 k 个病毒串,问有多少个字符串中不含有病毒串 题目分析:这个题目和之前做过的DNA的那个题有 ...

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

    题意:给出包含n个字符的字符集,以下所提字符串均由该字符集中的字符构成.给出p个长度不超过10的字符串,求长为m且不包含上述p个字符串的字符串有多少个. 数据范围:1<=n,m<=50,0 ...

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

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

最新文章

  1. 吴恩达演讲直指AI落地三大挑战,并提出解决方案
  2. MemCache详细解读
  3. fastq质量值_fastq 数据格式解析
  4. php 首页加背景图片,如何在页首添加一张背景图片
  5. php修改学生信息代码_值得收藏的CRM软件客户管理系统(包括JAVA/PHP)
  6. linux自动重启电脑脚本,linux下通过脚本实现自动重启程序的方法
  7. 我的MYSQL学习心得(十一) 视图
  8. HOJ——T 1867 经理的烦恼
  9. MacBook Pro 高功率模式:是如何工作的?
  10. 数字温度传感器DS18B20的数据手册理解
  11. centos转换linux格式,CentOS 下转换网易云音乐ncm格式为mp3
  12. 自动发消息到微信提醒
  13. Windows电脑端有什么好用的便签工具?
  14. loj10099 点双连通分量
  15. supersu二进制更新安装失败_Supersu提示更新二进制文件解决方案
  16. java populate_BeanUtils.populate()的用法
  17. 论文阅读-MLPD:Multi-Label Pedestrian Detector in Multispectral Domain(海康威视研究院实习项目)
  18. AI教程 如何在 Illustrator 中创建渐变颜色?
  19. 蘑菇街Java后台开发一二面面经
  20. oracle INSTR函数的介绍

热门文章

  1. H5 AUI 使用总结
  2. IDEA中HTML文档快速制作table表格快捷键方法
  3. 六下计算机教学总结,六年级下册信息技术教学工作总结
  4. 纯干货分享,2021年阿里巴巴社招面试题总结,本人上周已成功入职!
  5. 推荐一本好书《 Java程序员 上班那点事儿》
  6. 销售订单(Sales Order)流程
  7. WPF 逻辑树和可视化树
  8. 自动取款机 冲正交易
  9. Java对象内存大小计算
  10. 结构化英语查询语言SQL