ZOJ 3494
超级神奇有趣题。
AC自动机+数位DP。其实,数位DP在处理含有某些数字时特别不好处理,应该把它倒转为求不含有。这道题把数位DP+AC自动机结合起来,实在是很巧妙,把数字变为串来处理,强大!
要使用AC自动机来处理数位DP,首先就是要确定哪些状态由当前状态开始是不可以到达的,有哪些是可以到达的。这是显而易见的,因为既然是数位DP,必定涉及到数字的问题,每改变一个数字就会到达自动机上的一个状态,确定哪些状态可达或不可达是很有必要的。这就要求要构建trie图了。
其次就是DFS了,在进行DFS深搜前,要确定当前状态变更一个数字后的状态是否可达,再进行转移。
在这题,要处理前导0的问题,因为0000(十进制)里,其实只代表一个0,但可能会出现禁止状态(如二进制连续五个0违法,但四个0不违法)。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;
const LL MOD=;
const int root=;
int trie[][],tot,bit[];
int next[][],fail[];
bool tag[];
char str[];
LL dp[][];
int que[],head,tail; void clr(int now){
trie[now][]=trie[now][]=-;
} void insert(){
int p=root,i=,len=strlen(str);
while(i++<len){
if(trie[p][str[i-]-'']==-){
trie[p][str[i-]-'']=++tot;
clr(tot);
}
p=trie[p][str[i-]-''];
}
tag[p]=true;
} void build_ac(){
head=tail=;
que[tail++]=root;
while(head!=tail){
int tmp=que[head++];
int p=-;
for(int i=;i<;i++){
if(trie[tmp][i]!=-){
if(tmp==root) fail[trie[tmp][i]]=root;
else{
p=fail[tmp];
while(p!=-){
if(trie[p][i]!=-){
fail[trie[tmp][i]]=trie[p][i];
break;
}
p=fail[p];
}
if(p==-) fail[trie[tmp][i]]=root;
}
if(tag[fail[trie[tmp][i]]]) tag[trie[tmp][i]]=tag[fail[trie[tmp][i]]];
que[tail++]=trie[tmp][i];
}
else{
if(tmp==root) trie[tmp][i]=root;
else{
p=fail[tmp];
while(p!=-){
if(trie[p][i]!=-){
trie[tmp][i]=trie[p][i];
break;
}
p=fail[p];
}
if(p==-) trie[tmp][i]=root;
}
}
}
}
} void interval(){
int len=strlen(str)-;
char tmp;
for(int i=len;i>=len-i;i--){
tmp=str[i];
str[i]=str[len-i];
str[len-i]=tmp;
}
} int cal_next(int p,int j){
if(tag[p]) return -;
for(int k=;k>=;k--){
p=trie[p][(j>>k)&];
if(tag[p]) return -;
}
return p;
} void Calculation(){
for(int i=;i<=tot;i++){
for(int j=;j<=;j++){
next[i][j]=cal_next(i,j);
}
}
} LL dfs(int len,int j,bool limit,bool z){
if(len==-) return 1LL;
if(!limit&&dp[len][j]!=-) return dp[len][j];
int up=limit?bit[len]:;
LL ans=;
if(z&&len>){
ans+=dfs(len-,j,limit&&up==,true);
}
else{
if(next[j][]!=-&&!tag[next[j][]])
ans+=dfs(len-,next[j][],limit&&up==,false);
}
for(int i=;i<=up;i++){
if(next[j][i]!=-&&!tag[next[j][i]]){
ans+=dfs(len-,next[j][i],limit&&i==up,false);
}
}
ans%=MOD;
if(!limit) dp[len][j]=ans;
return ans;
} LL slove(){
int len=strlen(str);
len--;
for(int i=len;i>=;i--)
bit[i]=str[i]-'';
return dfs(len,,true,true);
} int main(){
int T,n,len;
scanf("%d",&T);
while(T--){
memset(tag,false,sizeof(tag));
memset(dp,-,sizeof(dp));
memset(fail,-,sizeof(fail));
scanf("%d",&n);
tot=;
clr(root);
for(int i=;i<n;i++){
scanf("%s",str);
// cout<<str<<endl;
insert();
}
build_ac();
Calculation();
scanf("%s",str);
// cout<<str<<endl;
len=strlen(str);
interval();
// cout<<str<<endl;
for(int i=;i<len;i++){
if(str[i]=='')
str[i]='';
else {
str[i]--;
break;
}
}
if(str[len-]==''&&len!=) str[len-]='\0';
LL ans1=slove();
scanf("%s",str);
interval();
// memset(dp,-1,sizeof(dp));
LL ans2=slove();
printf("%lld\n",((ans2-ans1)%MOD+MOD)%MOD);
}
return ;
}
ZOJ 3494的更多相关文章
- ZOJ 3494 (AC自动机+高精度数位DP)
题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3494 题目大意:给定一些被禁止的BCD码.问指定范围内不含有 ...
- ZOJ 3494 BCD Code(AC自动机+数位DP)
BCD Code Time Limit: 5 Seconds Memory Limit: 65536 KB Binary-coded decimal (BCD) is an encoding ...
- zoj 3494:BCD Code
Description Binary-coded decimal (BCD) is an encoding for decimal numbers in which each digit is rep ...
- ZOJ 3494 BCD Code (数位DP,AC自动机)
题意: 将一个整数表示成4个bit的bcd码就成了一个01串,如果该串中出现了部分病毒串,则是危险的.给出n个病毒串(n<=100,长度<21),问区间[L,R]中有几个数字是不含病毒串的 ...
- ZOJ 3494 BCD Code (AC自己主动机 + 数位DP)
题目链接:BCD Code 解析:n个病毒串.问给定区间上有多少个转换成BCD码后不包括病毒串的数. 很奇妙的题目. . 经典的 AC自己主动机 + 数位DP 的题目. 首先使用AC自己主动机,得到b ...
- BCD Code ZOJ - 3494 AC自动机+数位DP
题意: 问A到B之间的所有整数,转换成BCD Code后, 有多少个不包含属于给定病毒串集合的子串,A,B <=10^200,病毒串总长度<= 2000. BCD码这个在数字电路课上讲了, ...
- ZOJ 3494 BCD Code(AC自动机 + 数位DP)题解
题意:每位十进制数都能转化为4位二进制数,比如9是1001,127是 000100100111,现在问你,在L到R(R <= $10^{200}$)范围内,有多少数字的二进制表达式不包含模式串. ...
- AC自动机-算法详解
What's Aho-Corasick automaton? 一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模式匹配算法之一. 简单的说,KMP用来在一篇文章中匹配一个模式串:但 ...
- 【原创】AC自动机小结
有了KMP和Trie的基础,就可以学习神奇的AC自动机了.AC自动机其实就是在Trie树上实现KMP,可以完成多模式串的匹配. AC自动机 其实 就是创建了一个状态的转移图,思想很 ...
随机推荐
- 洛谷 P3959 NOIP2017 宝藏 —— 状压搜索
题目:https://www.luogu.org/problemnew/show/P3959 搜索: 不是记忆化,而是剪枝: 邻接矩阵存边即可,因为显然没有那么多边. 代码如下: #include&l ...
- 用SQL实现统计报表中的“小计”和“合计”
问题: 开发一个关于各烟叶等级的二次验级的原发件数.原发重量及验收重量的统计报表.其中,原发件数.原发重量和验收重量等列要求计算出各等级组别的小计和所有记录的合计. 语句: SELECT DECODE ...
- scrollTop,scrollHeight,clientTop,clientHeight,offsetTop,offsetHeight实际意义 及 计算方式 附实例说明
一.滚动距离.高度 scrollTop scrollLeft scrollHeight scrollWidth 二.相对位置.距离 offsetTop offsetLeft offsetHeight ...
- c# 官方文档必看
https://docs.microsoft.com/zh-cn/dotnet/csharp/whats-new/csharp-version-history
- Windows 环境下 Docker 使用及配置
原文引用: https://www.cnblogs.com/moashen/p/8067612.html 我们可以使用以下两种方式在Windows环境下使用docker: 1. 直接安装: Docke ...
- Laravel5.1学习笔记10 系统架构2 应用程序结构
应用程序结构 简介 根目录 App 目录 为应用程序设置命名空间 简介 默认的 Laravel 应用程序结构是为了给无论构建大型还是小型应用程序都提供一个良好的开始.当然,你可以依照喜好自由地组织应用 ...
- inline-block默认间距解决方法
方法一: 父元素设置font-size: 0; 行内块元素有文字时再在该元素上设置font-size 方法二: 父元素设置word-spacing为负 方法三: Inline-block 元素浮 ...
- Ubuntu16下安装lamp
1.安装php7 sudo apt-get install php7.0 php7.0-mcrypt 2.安装MySQL sudo apt-get install mysql-server 输入 su ...
- creat-react-app 支持 less
yarn eject yarn add less less-loader config/ webpack.config.dev.js config/ webpack.config.prod.js 文 ...
- 安卓代码迁移:Program "sh" not found in PATH
Description Resource Path Location Type Program "sh" not found in PATH 参考链 ...