URAL 1158 AC自动机上的简单DP+大数
题目大意
在一种语言中的字母表中有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+大数的更多相关文章
- 【洛谷4045】[JSOI2009] 密码(状压+AC自动机上DP)
点此看题面 大致题意: 给你\(n\)个字符串,问你有多少个长度为\(L\)的字符串,使得这些字符串都是它的子串.若个数不大于\(42\),按字典序输出所有方案. 状压 显然,由于\(n\)很小,我们 ...
- POJ 3691 AC自动机上的dp
题目大意: 给定一些不合理的DNA序列,再给一段较长的dna序列,问最少修改几次可以使序列中不存在任何不合理序列,不能找到修改方法输出-1 这里你修改某一个点的DNA可能会影响后面,我们不能单纯的找匹 ...
- HNU 13108-Just Another Knapsack Problem (ac自动机上的dp)
题意: 给你一个母串,多个模式串及其价值,求用模式串拼接成母串(不重叠不遗漏),能获得的最大价值. 分析: ac自动机中,在字典树上查找时,用dp,dp[i]拼成母串以i为结尾的子串,获得的最大价值, ...
- 【BZOJ1030】[JSOI2007] 文本生成器(AC自动机上跑DP)
点此看题面 大致题意: 给你\(N\)个字符串(只含大写字母),要你求出有多少个由\(M\)个大写字母构成的字符串含有这\(N\)个字符串中的至少一个. \(AC\)自动机 看到题目,应该比较容易想到 ...
- Passwords Gym - 101174E (AC自动机上DP)
Problem E: Passwords \[ Time Limit: 1 s \quad Memory Limit: 256 MiB \] 题意 给出两个正整数\(A,B\),再给出\(n\)个字符 ...
- BZOJ 1030 文本生成器 | 在AC自动机上跑DP
题目: http://www.lydsy.com/JudgeOnline/problem.php?id=1030 题解: 鸽 #include<cstdio> #include<al ...
- bzoj [Sdoi2014]数数 AC自动机上dp
[Sdoi2014]数数 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1264 Solved: 636[Submit][Status][Discu ...
- 【Luogu】P3311数数(AC自动机上DP)
题目链接 蒟蒻今天终于学会了AC自动机,感觉很稳 (后一句愚人节快乐) 这题开一个f[i][j][k]表示有没有受到限制,正在枚举第j位,来到了AC自动机的第k个节点 的方案数 随后可以刷表更新 注意 ...
- hdu 3992 AC自动机上的高斯消元求期望
Crazy Typewriter Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
随机推荐
- git的作用和原理(待续)
先选定一个目录作为Git仓库,假定是/srv/sample.git,在/srv目录下输入命令: $ sudo git init --bare sample.git Git就会创建一个裸仓库,裸仓库没有 ...
- 转:C/C++中,空数组、空类、类中空数组的解析及其作用
转自:http://blog.sina.com.cn/s/blog_93b45b0f01015s95.html 我们经常会遇到这些问题: (1)C++中定义一个空类,他们它的大小(sizeof) 为多 ...
- paramiko-客户端和服务器认证工具
required: python+pycrypto 1.安装pycrypto 726 cd /opt/ 727 wget http://ftp.dlitz.net/pub/dlitz/crypto/p ...
- Sun Grid Engine (SGE)大型集群作业调度系统
Oracle Grid Engine 作业调度系统的简介(目前为止我用过PBS和SGE) SGE作业调度系统学习笔记 SGE作业调度 USE of Sun Grid Engine(SGE) 待续~
- 测序原理 - PacBio技术资料
手头有一套完整的PacBio技术资料,会慢慢的总结到博客上. 写在前面:PacBio公司主要有两个测序平台一个是RS,一个是最新的Sequel,下面如果没有指明则是在讲RS平台. SMRT测序技术总览 ...
- React Native For Android 架构初探
版权声明:本文由王少鸣原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/171 来源:腾云阁 https://www.qclo ...
- Spring表达式语言 之 5.1 概述 5.2 SpEL基础(拾叁)
5.1 概述 5.1.1 概述 Spring表达式语言全称为"Spring Expression Language",缩写为"SpEL",类似于Struts ...
- JavaScript 运行机制详解:再谈Event Loop
原文地址:http://www.ruanyifeng.com/blog/2014/10/event-loop.html 一年前,我写了一篇<什么是 Event Loop?>,谈了我对Eve ...
- 安装Ubuntu Linux系统时硬盘分区最合理的方法
无论是安装Windows还是Linux操作系统,硬盘分区都是整个系统安装过程中最为棘手的环节,网上的一些Ubuntu Linux安装教程一般都是自动分区,给初学者带来很大的不便,下面我就根据多年来在合 ...
- [mondrian] 快速入门
一.下载地址 mondrian各个版本和工具等的下载地址: http://sourceforge.net/projects/mondrian/files/?source=navbar 注意:mondr ...