题目大意

在一种语言中的字母表中有N(N<=50)个字母,每个单词都由M(M<=50)个字母构成,因此,一共可以形成N^M个单词。但是有P(P<=10)个串是被禁止的,也就是说,任何单词的子串都不能包含这P个串中的任意一个。问按照上述规则,能产生的合法串一共有多少个? 例如:N=3 M=3 P=3 字母表中的三个字符是QWE 被禁止的串为”QQ”,”WEE”,”Q”,则合法的串一共有7个。

这题目相当于通过步数对AC自动机上每一个点的状态进行DP

dp[i][j]表示到达i这个点,走了j步存在多少种方法

总是从上一步推到下一步

写成滚动数组也不会有问题

这里要注意在AC自动机更新操作时,要将每个串末尾能到达的fail位置也记上标记,题解中有注释解释

 #include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
#define clr(x) memset(x , 0 , sizeof(x))
#define set(x) memset(x , -1 , sizeof(x))
typedef long long LL ;
#define rep( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define For( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define rev( i , a , b ) for ( int i = a ; i >= b ; -- i )
map<char , int> mp; const int CHAR_SIZE = ;
const int MAX_SIZE = ;
const int M = ;
int n,m,p; struct BigInt {
int wei , a[];
BigInt(){
wei = ;
memset(a , , sizeof(a));
}
void init(){
wei = ;
memset(a , , sizeof(a));
}
void print(){
for(int i=wei- ; i>= ; i--) printf("%d" , a[i]);
printf("\n");
}
BigInt operator+(BigInt m){
BigInt ret;
int ma = max(wei , m.wei);
for(int i= ; i<ma ; i++){
ret.a[i] += a[i]+m.a[i];
if(ret.a[i]>=) ret.a[i+]++,ret.a[i]-=;
}
if(ret.a[ma]) ret.wei = ma+;
else ret.wei = ma;
return ret;
}
}; struct AC_Machine{
int ch[MAX_SIZE][CHAR_SIZE] , val[MAX_SIZE] , fail[MAX_SIZE];
int sz; void init(){
sz = ;
clr(ch[]) , clr(val);
} void insert(char *s){
int n = strlen(s);
int u= ;
for(int i= ; i<n ; i++){
int c = mp[s[i]];
if(!ch[u][c]){
clr(ch[sz]);
val[sz] = ;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = ;
} void get_fail(){
queue<int> Q;
fail[] = ;
for(int c= ; c<n ; c++){
int u = ch[][c];
if(u){Q.push(u);fail[u]=;}
}
while(!Q.empty()){
int r = Q.front();
Q.pop();
//比如is, history都是非法的,history中有is,那么history访问到它的s时也是非法的
val[r] |= val[fail[r]];
for(int c= ; c<n ; c++){
int u = ch[r][c];
if(!u){ch[r][c] = ch[fail[r]][c]; continue;}
fail[u] = ch[fail[r]][c];
Q.push(u);
}
}
}
}ac; char str[];
BigInt dp[MAX_SIZE][]; BigInt solve(int n , int step)
{
for(int i= ; i<ac.sz ; i++)
for(int j= ; j<=step ; j++){
dp[i][j].init();
}
dp[][].wei = dp[][].a[] = ;
for(int i= ; i<=step ; i++){
for(int j= ; j<ac.sz ; j++){
for(int k= ; k<n ; k++)
if(!ac.val[ac.ch[j][k]]){
dp[ac.ch[j][k]][i] = dp[ac.ch[j][k]][i]+dp[j][i-];
}
}
}
BigInt ret = BigInt();
for(int j= ; j<ac.sz ; j++) ret = ret+dp[j][step];
return ret;
} int main()
{
// freopen("in.txt" , "r" , stdin);
// freopen("out.txt" , "w" , stdout);
while(~scanf("%d%d%d" , &n , &m , &p)){
mp.clear();
getchar();
gets(str);
for(int i= ; i<strlen(str) ; i++) mp[str[i]] = i;
ac.init();
for(int i= ; i<=p ; i++){
gets(str);
ac.insert(str);
}
ac.get_fail();
BigInt ret = solve(n , m);
ret.print();
}
return ;
}

URAL 1158 AC自动机上的简单DP+大数的更多相关文章

  1. 【洛谷4045】[JSOI2009] 密码(状压+AC自动机上DP)

    点此看题面 大致题意: 给你\(n\)个字符串,问你有多少个长度为\(L\)的字符串,使得这些字符串都是它的子串.若个数不大于\(42\),按字典序输出所有方案. 状压 显然,由于\(n\)很小,我们 ...

  2. POJ 3691 AC自动机上的dp

    题目大意: 给定一些不合理的DNA序列,再给一段较长的dna序列,问最少修改几次可以使序列中不存在任何不合理序列,不能找到修改方法输出-1 这里你修改某一个点的DNA可能会影响后面,我们不能单纯的找匹 ...

  3. HNU 13108-Just Another Knapsack Problem (ac自动机上的dp)

    题意: 给你一个母串,多个模式串及其价值,求用模式串拼接成母串(不重叠不遗漏),能获得的最大价值. 分析: ac自动机中,在字典树上查找时,用dp,dp[i]拼成母串以i为结尾的子串,获得的最大价值, ...

  4. 【BZOJ1030】[JSOI2007] 文本生成器(AC自动机上跑DP)

    点此看题面 大致题意: 给你\(N\)个字符串(只含大写字母),要你求出有多少个由\(M\)个大写字母构成的字符串含有这\(N\)个字符串中的至少一个. \(AC\)自动机 看到题目,应该比较容易想到 ...

  5. Passwords Gym - 101174E (AC自动机上DP)

    Problem E: Passwords \[ Time Limit: 1 s \quad Memory Limit: 256 MiB \] 题意 给出两个正整数\(A,B\),再给出\(n\)个字符 ...

  6. BZOJ 1030 文本生成器 | 在AC自动机上跑DP

    题目: http://www.lydsy.com/JudgeOnline/problem.php?id=1030 题解: 鸽 #include<cstdio> #include<al ...

  7. bzoj [Sdoi2014]数数 AC自动机上dp

    [Sdoi2014]数数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1264  Solved: 636[Submit][Status][Discu ...

  8. 【Luogu】P3311数数(AC自动机上DP)

    题目链接 蒟蒻今天终于学会了AC自动机,感觉很稳 (后一句愚人节快乐) 这题开一个f[i][j][k]表示有没有受到限制,正在枚举第j位,来到了AC自动机的第k个节点 的方案数 随后可以刷表更新 注意 ...

  9. hdu 3992 AC自动机上的高斯消元求期望

    Crazy Typewriter Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

随机推荐

  1. overridePendingTransition动画只设置一个

    退出动画可以设置为0, 但是两个动画的duration需要一样. 退出动画:<?xml version="1.0" encoding="utf-8"?&g ...

  2. Multipath多路径冗余全解

    一.什么是multipath 普通的电脑主机都是一个硬盘挂接到一个总线上,这里是一对一的关系.而到了有光纤组成的SAN环境,由于主机和存储通过了光纤交换机连接,这样的话,就构成了多对多的关系.也就是说 ...

  3. SqlServer_事务

    事务处理是在数据处理时经常遇到的问题,经常用到的方法有以下三种总结整理如下:方法1:直接写入到sql 中在存储过程中使用 BEGIN TRANS, COMMIT TRANS, ROLLBACK TRA ...

  4. Oracle Names - Oracle_SID /db_name instance_name service_names / service_name / sid / sid_name

    很多人还是困惑,下面再次尝试从几个不同角度区分一下: Oracle_SID / db_name, instance_name, service_names  / service_name, sid / ...

  5. 20160808_Qt570安装

    1.安装的目录为 “/opt/Qt5.7.0/Tools/QtCreator/bin” 2.建立软连接 [root@localhost bin]# ln -s /opt/Qt5.7.0/Tools/Q ...

  6. CSS三种定位机制

    标准文档流 块级元素撑满整个页面div,ul,li,dl,dt,p 行级元素可以一行显示多个span,strong,img,input大部分 一般不设置盒子的高度,另其自动调整 margin属性的au ...

  7. Python设计模式之单例模式

    1.由于语言的特性不同,设计模式的实现方式和实现难度也会不同 2.有的模式已经在语言内置了,比如迭代器模式. 3.单例模式可以直接用模块级变量来实现 4.普通工厂模式可以直接通过传入"类名& ...

  8. michael的沟通秘籍

    1 多准备几个邮件模板2 lower expectation over delivery less promise extra give3 involve resource earliar 尽早接手公 ...

  9. PHP 递归的密码

    http://www.cnsecer.com/4146.html 说实话 真的很炫 好像还是不好理解啊

  10. vsphere vcenter 添加域管理员

    选择 vcenter server  管理权限