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自动机 其实 就是创建了一个状态的转移图,思想很 ...
随机推荐
- 【POJ 3074】 Sudoku
[题目链接] http://poj.org/problem?id=3074 [算法] 将数独问题转化为精确覆盖问题,用Dancing Links求解 转化方法如下 : 我们知道,在一个数独中 : 1. ...
- python mysql数据库 'latin-1' codec can't encode character错误问题解决
"UnicodeEncodeError:'latin-1' codec can't encode character ..." This is because MySQLd ...
- 基于Spark ML的Titanic Challenge (Top 6%)
下面代码按照之前参加Kaggle的python代码改写,只完成了模型的训练过程,还需要对test集的数据进行转换和对test集进行预测. scala 2.11.12 spark 2.2.2 packa ...
- PCB 后台自动系统集成与邮件推送实现
在PCB行业中,工程系统是主要数据生产者,而这些数据不仅仅给自己系统使用呀,我们需要将数据传递到各系统,才达到各系统共同协作的目的. 这里以问答方式对实现方式进行讲解.呵呵呵! 后台自动集成问题解答: ...
- 图结构练习—BFSDFS—判断可达性(BFS)
http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2138 注意该图为有向图,1000个点应该最多有 ...
- js getyear和getfullyear
getyear()函数如果今年是2015年会得到115,getfullyear()会得到完整的年份.
- HTML <!DOCTYPE>标签
一般一个基本html页面的结构,如下代码所示: <html> <head> <title>我是基本的页面结构</title> </head> ...
- MYSQL日期时间字符串互转
--MYSQL date_format(date,'%Y-%m-%d') -------------->oracle中的to_char(); 日期时间转字符串 --MYSQL str_to_da ...
- scrollWidth clientWidth offsetWidth
scrollWidth:对象的实际内容的宽度,不包边线宽度,会随对象中内容超过可视区后而变大. 实际内容+padding 不包括滚动条 边框client ...
- 非内置浏览器WebView 调起H5支付,提示商家参数格式有误
微信H5 支付开发官方文档参考资料: https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_4 0. 场景描述:在APP 中使用webVie ...