AC自动机+数位DP。

  大致题意:

    BCD码就是把一个数十进制下的每一位分别用4位的二进制表示。

    给你一坨01串,问你在一个区间内,有多少个数的BCD码不包含任何一个字符串。

  因为涉及到多个串的匹配问题...所以要在AC自动机上DP

  f[i][j]表示在自动机上的节点i,再往后走j步 的合法方案数。(合法就是说,经过的路径上不包含任何一个给定字符串)

  建完AC自动机后,把非法的节点都删掉,再求出CH[i][j]表示从i节点出发,经过数字j后到达的节点(0<=j<=9),这样好转移= =。

  一开始想写递归版本的。。前导0什么的完全无力TAT

  后来干脆用记忆化搜索求f数组,然后统计答案的时候用正常姿势。。这样好写多了>_<

  结果交完直接#1了。。我是没看出来自己的写法哪里常数优越= =

  其实这题只比普通模版题多了个AC自动机而已。。。其他甚至还简单点

  就算是递归版的,只要好好想一下前导零的问题就行了吧...网上递归版的标程也不长

 #include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int modd=;
int fail[],ch[][];
int CH[][];
int f[][],u[][];//f[i][j]在自动机上的i节点时,再往后走j步的合法方案数
int i,j,k,n,m,tot,T,ans,len;
bool gg[]; char s[];int dl[]; inline void insert(int len){
int i,now=;
for(i=;i<len;i++)
s[i]-='',now=ch[now][s[i]]?ch[now][s[i]]:(ch[now][s[i]]=++tot);
gg[now]=;
}
inline void build(){
int l=,r=,i,now,tmp;
while(l<r){
now=dl[++l];
for(i=;i<=;i++)if(ch[now][i]){
for(tmp=fail[now];tmp&&!ch[tmp][i];tmp=fail[tmp]);
fail[ch[now][i]]=(now==)?:ch[tmp][i]; gg[ch[now][i]]|=gg[fail[ch[now][i]]]|gg[now];
dl[++r]=ch[now][i];
}else{
for(tmp=fail[now];tmp&&!ch[tmp][i];tmp=fail[tmp]);
ch[now][i]=ch[tmp][i];
}
}
for(i=;i<=tot;i++)for(j=;j<=;j++)if(gg[ch[i][j]]||gg[i])ch[i][j]=-;
for(i=;i<=tot;i++)if(!gg[i])
for(j=;j<=;j++){
for(now=i,k=;k&&now!=-;k>>=)
now=ch[now][(k&j)!=];
CH[i][j]=now;//printf(" %d->%d %d\n",i,j,CH[i][j]);
}
for(i=;i<=tot;i++)if(!gg[i])f[i][]=,u[i][]=T;
}
inline int dfs(int x,int step){
if(u[x][step]==T)return f[x][step];
int ans=;
for(int i=;i<=;i++)if(CH[x][i]!=-)
ans+=dfs(CH[x][i],step-),ans-=ans>=modd?modd:;
u[x][step]=T,f[x][step]=ans;//printf(" f: %d %d %d\n",x,step,f[x][step]);
return ans;
}
inline int get(int len){//求区间[1,len)内合法方案数
register int i,j,ans=,now;
for(i=;i<len;i++)s[i]-=;
for(i=;i<len;i++)for(j=;j<=;j++)if(CH[][j]!=-)
ans+=dfs(CH[][j],i-),ans-=ans>=modd?modd:;
for(i=;i<s[];i++)if(CH[][i]!=-)ans+=dfs(CH[][i],len-),ans-=ans>=modd?modd:; now=CH[][s[]];
for(i=;i<len&&now!=-;i++){
for(j=;j<s[i];j++)if(CH[now][j]!=-)ans+=dfs(CH[now][j],len-i-),ans-=ans>=modd?modd:;
now=CH[now][s[i]];
}
return ans;
}
inline void add(){
int i,j;
for(i=len-;i>=;i--)if(s[i]!='')break;
if(i>=)
for(s[i]++,j=i+;j<len;j++)s[j]='';
else{
for(s[]='',i=;i<=len;i++)s[i]='';
len++;
}
}
int main(){
for(scanf("%d",&T);T;T--){
scanf("%d",&n);memset(gg,,tot+);memset(ch,,(tot+)<<);tot=;
for(i=;i<=n;i++)
scanf("%s",s),insert(strlen(s));
build();
scanf("%s",s);len=strlen(s);ans=-get(len);
scanf("%s",s);len=strlen(s);add();ans+=get(len);
if(ans<)ans+=modd;
printf("%d\n",ans);
}
return ;
}

[ZOJ3494]BCD Code的更多相关文章

  1. zoj3494 BCD Code(AC自动机+数位dp)

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

  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 (AC自己主动机 + 数位DP)

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

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

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

  5. zoj 3494:BCD Code

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

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

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

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

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

  8. FZU 2113 BCD Code 数位dp

    数位dp,但是很奇怪的是我在虚拟oj上用GUC C++提交会wa,用Visual c++提交正确,但是加上注释后提交又莫名CE--好任性啊 0 ,0 题目思路:看代码吧 注释很详细 #include& ...

  9. [转]数位dp小记

    转载自:http://blog.csdn.net/guognib/article/details/25472879 参考: http://www.cnblogs.com/jffifa/archive/ ...

随机推荐

  1. 串String(1):串的实现(定长顺序存储结构)

    前言 PS:本文相关头文件.预编译以及typedef如下,阅读一遍以便于下面的理解: #include <stdio.h> #include <stdlib.h> #inclu ...

  2. 用VS2015写一个简单的ASP.net网站

    第一步:打开VS2015,然后新建一个空的解决方案,其中解决方案的名称WebSiteTest可类似认为是本次网站的名称,系统会以该名称(WebSiteTest)生成一个文件夹,在WebSites文件夹 ...

  3. ABP .Net Core API和Angular前端APP集成部署

    前言:在ABP官网(https://aspnetboilerplate.com)生成的.Net Core + Angular项目前后端是两个独立的项目,我们可以分开部署,也可以将前端和Web API一 ...

  4. java I/O---复制文本文件

    利用FileInputStream 和FileOutputStream 复制文本 1 public class CopyTextByBuffer { 2 3 /** 4 * @param args 5 ...

  5. xamarin Android activity生命周期详解

    学Xamarin我为什么要写这样一篇关于Android 的activity生命周期的文章 已经学Xamarin android有一段时间了,现在想起当初Xamarin也走了不少的弯路.当然Xamari ...

  6. c#$用法

    为什么会出现$符号,c#6.0才出现的新特性 var s = string.Fromat("{0}+{1}={2}",12,23,12+23) 用起来必须输入string.From ...

  7. Equilibrium point

    Given an array A your task is to tell at which position the equilibrium first occurs in the array. E ...

  8. UVA 11825 Hackers' Crackdown

    题目大意就是有一个图,破坏一个点同时可以破坏掉相邻点.每个点可以破坏一次,问可以完整破坏几次,点数=16. 看到16就想到状压什么的. 尝试设状态:用f[i]表示选的情况是i(一个二进制串),至少可以 ...

  9. websocket教程(一) 非常有趣的理解websocket

    一.websocket与http WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持持久连接的(长连接,循环连接的不算) 首先HTTP有 1 ...

  10. Unix 文件系统读写时权限校验

    文件系统中的所有文件都是在读出或写入时进行权限校验 一个问题,如果一个用户对一个普通文件有读写权限,在使用vim编辑时,管理员撤销掉此用户对此文件的写入权限 那么,这个普通用户还可以将修改写入文件吗?