博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ZOJ 3494 BCD Code (数位DP,AC自动机)
阅读量:5155 次
发布时间:2019-06-13

本文共 2146 字,大约阅读时间需要 7 分钟。

 

 

题意:

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

 

思路:

  区间非常大,怎样暴力统计都是不科学的。首先确定状态,按传统,一维必定是位数,二维就是压缩的状态了,如果长度为20个bit的话,200*104万的数组是不行的。类似多模式串匹配问题,病毒串可以构建成AC自动机,那么每个点可以代表一个独立状态,而n<=100,所以最多20n个节点,是可以的。转移的话可以根据新考虑的数位是多少,然后在AC自动机上面走4步(BCD码是4bit)到达另一个状态(点),如果经过了病毒串的末尾节点,表示该数出现病毒串,就不能转移。这个可以在AC自动机创建完成后,预处理出来就行了。而对于每个询问[L,R],L仍然是需要减1的,大数减1比较简单。注意点是,AC自动机上的tag需要特殊处理,如果有病毒串"asdf"和串"sd",而碰到原串为"asdd",别忘了还有"sd"。这只需要在构建fail指针的时候处理一下。

 

 

 

 

 

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #define pii pair
11 #define INF 0x7f3f3f3f 12 #define LL long long 13 #define ULL unsigned long long 14 using namespace std; 15 const double PI = acos(-1.0); 16 const int N=210; 17 const LL mod=1000000009; 18 19 struct Trie{ 20 static const int NN=2100; //节点数 21 static const int CC=2; //孩子数 22 int next[NN][CC], fail[NN]; 23 bool tag[NN]; 24 int root, node_cnt; 25 int newnode(){ 26 for(int i=0; i
que; 46 for(int i=0; i
0? 0: 1; //起 86 int u= e? bit[i]-'0': 9;//终 87 for(; d<=u; d++) 88 { 89 if(bcd[s][d]!=-1) 90 { 91 ans+=dfs(i-1, bcd[s][d], sum+d, e&&d==u); 92 ans%=mod; 93 } 94 } 95 if(!e&&sum) f[i][s]=ans; //没有前导零 96 return ans; 97 } 98 99 100 LL cal()101 {102 reverse(bit+1, bit+len+1);103 if(len==1&&bit[len]=='0') return 1;104 return dfs(len, 0, 0, true);105 }106 107 int changeto(int s,int t)108 {109 if(AC.tag[s]) return -1; //已经是病毒串110 int now=s;111 for(int i=3; i>=0; i--)112 {113 if( AC.tag[AC.next[now][(t>>i)&1]]==1 ) return -1; //病毒串114 now=AC.next[now][(t>>i)&1];115 }116 return now;117 }118 void pre_cal() //预处理转移119 {120 for(int i=0; i
>t;128 LL ans[2];129 while( t-- )130 {131 memset(bcd, -1, sizeof(bcd));132 memset(f, -1, sizeof(f));133 AC.init();134 scanf("%d",&n);135 for(int i=0; i
0; i--) //注意逆序150 {151 if( bit[i]>'0' ){bit[i]--;break;}152 else bit[i]='9';153 }154 }155 ans[j]=cal();156 }157 printf("%lld\n",(ans[1]+mod-ans[0])%mod);158 }159 return 0;160 }
AC代码

 

转载于:https://www.cnblogs.com/xcw0754/p/4857334.html

你可能感兴趣的文章
JAVA中properties基本用法
查看>>
MVC面试问题与答案
查看>>
jQuery分析(3) - jQuery.fn.init
查看>>
手动安装vue-devtools
查看>>
平衡二叉树【学习笔记】
查看>>
haproxy开启日志功能
查看>>
HorizontalScrollView 横向显示图片
查看>>
大道至简第四章读后感
查看>>
对象的动态特性
查看>>
析构函数 p157
查看>>
奇异值分解SVD应用——LSI
查看>>
Java-编程规范与代码风格
查看>>
关于 SAXParseException Content is not allowed in Prolog (前言中不允许有内容)
查看>>
.NET 动态向Word文档添加数据
查看>>
vue子组件向父组件传值
查看>>
cmf公共函数解析
查看>>
Java Socket分发服务负载均衡
查看>>
openwrt 设置samba服务器与pc共享文件
查看>>
做个顶天立地的人
查看>>
「8」条件语句
查看>>