超级神奇有趣题。

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的更多相关文章

  1. ZOJ 3494 (AC自动机+高精度数位DP)

    题目链接:  http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3494 题目大意:给定一些被禁止的BCD码.问指定范围内不含有 ...

  2. ZOJ 3494 BCD Code(AC自动机+数位DP)

    BCD Code Time Limit: 5 Seconds      Memory Limit: 65536 KB Binary-coded decimal (BCD) is an encoding ...

  3. zoj 3494:BCD Code

    Description Binary-coded decimal (BCD) is an encoding for decimal numbers in which each digit is rep ...

  4. ZOJ 3494 BCD Code (数位DP,AC自动机)

    题意: 将一个整数表示成4个bit的bcd码就成了一个01串,如果该串中出现了部分病毒串,则是危险的.给出n个病毒串(n<=100,长度<21),问区间[L,R]中有几个数字是不含病毒串的 ...

  5. ZOJ 3494 BCD Code (AC自己主动机 + 数位DP)

    题目链接:BCD Code 解析:n个病毒串.问给定区间上有多少个转换成BCD码后不包括病毒串的数. 很奇妙的题目. . 经典的 AC自己主动机 + 数位DP 的题目. 首先使用AC自己主动机,得到b ...

  6. BCD Code ZOJ - 3494 AC自动机+数位DP

    题意: 问A到B之间的所有整数,转换成BCD Code后, 有多少个不包含属于给定病毒串集合的子串,A,B <=10^200,病毒串总长度<= 2000. BCD码这个在数字电路课上讲了, ...

  7. ZOJ 3494 BCD Code(AC自动机 + 数位DP)题解

    题意:每位十进制数都能转化为4位二进制数,比如9是1001,127是 000100100111,现在问你,在L到R(R <= $10^{200}$)范围内,有多少数字的二进制表达式不包含模式串. ...

  8. AC自动机-算法详解

    What's Aho-Corasick automaton? 一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模式匹配算法之一. 简单的说,KMP用来在一篇文章中匹配一个模式串:但 ...

  9. 【原创】AC自动机小结

    有了KMP和Trie的基础,就可以学习神奇的AC自动机了.AC自动机其实就是在Trie树上实现KMP,可以完成多模式串的匹配.           AC自动机 其实 就是创建了一个状态的转移图,思想很 ...

随机推荐

  1. 【POJ 3322】 Bloxorz I

    [题目链接] http://poj.org/problem?id=3322 [算法] 广度优先搜索 [代码] #include <algorithm> #include <bitse ...

  2. element快速开发建站的动态UI------优

    网站快速成型工具 只为这样的你:  Element,一套为开发者.设计师和产品经理准备的基于 Vue 2.0 的组件库,提供了配套设计资源,帮助你的网站快速成型 http://element.elem ...

  3. git clone 出现错误

    看了好多资料终于搞定了git 中clone命令报错这个问题,废话不多说直接上步骤希望对大家有帮助. 1   删除.ssh文件夹(直接搜索该文件夹)下的known_hosts(手动删除即可,不需要git ...

  4. 【IDEA】(4)---很好用的DEBUG功能

    IDEA-DEBUG功能 一.常用快捷键 快捷键并不是完全一样的,我这边是MAC安装的IDEA, 这边最主要还是知道DEBUG时常用的功能. 1.快捷键 F7 #进入下一步,如果当前行是一个方法,则进 ...

  5. python 13:数字列表统计方法(min(list)、max(list)、sum(list))

    numbers = list(range(1,11)) print(numbers) print(min(numbers)) #获得列表最小值 print(max(numbers)) #获得列表最大值 ...

  6. 脑洞大开加偏执人格——可持久化treap版的Link Cut Tree2

    试了一下先上再下的Treap方式,很高兴,代码变短了,但是,跑的变慢了!!!其实慢得不多,5%左右.而且这个版本的写法不容易写错..只要会一般可持久化Treap的人写着都不难...就是相对于(压行的) ...

  7. vs2008 启动IE浏览器 出现DW20.exe占用大量cpu 服务器iis 异常调试

    DW20.exe占用大量cpu 服务器iis运行出现异常想查一下故障原因,发现有好几个DW20.exe进程,每个占用20%左右的cpu,在任务管理器中将其终止后,它又自动运行起来了 查了一下DW20. ...

  8. jquery学习之$(document).ready()

    参考资料: 1.W3School在线教程:http://www.w3school.com.cn/jquery/event_ready.asp 2.某人博客园:http://www.cnblogs.co ...

  9. 【系列】Java多线程初学者指南(1):线程简介

    原文地址:http://www.blogjava.net/nokiaguy/archive/2009/nokiaguy/archive/2009/03/archive/2009/03/19/26075 ...

  10. jQuery中容易让人困惑的东西

    前言:jqueryt很灵活,太灵活了,可以说是他一个优点,也是他一个缺点,达到一种效果,十个人也许会用十种不同的方法来实现这个过程,结果一样,过程不一样,这到底是好,还是坏呢. 一,什么是jquery ...