ZOJ 3494 BCD Code(AC自动机+数位DP)
来源:互联网 发布:广东网络作家协会 编辑:程序博客网 时间:2024/04/30 12:51
题意:给出一些禁止串,问从A~B的数字用BCD码表示,并且不包含禁止串的数有多少。
思路:首先用禁止串建立AC自动机,然后数位DP……dp[i][j]表示在位置i,状态为j时的合法数字个数。另外,如果最高位是0,那么这是不能被算在内的,所以,要再用个值来表示前面是否全为0。
代码:
#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<set>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn=2000+10;const int maxl=200+10;const int mod=1000000009;int ch[maxn][2],next[maxn],flag[maxn],size;int num[maxl],dp[maxl][maxn];char str[maxn];void Init(){ ch[0][0]=ch[0][1]=0; memset(next,0,sizeof(next)); flag[0]=size=0; memset(dp,0xff,sizeof(dp));}void Insert(const char *s){ int u=0,n=strlen(s); for(int i=0;i<n;++i) { int c=s[i]-'0'; if(!ch[u][c]) { ch[u][c]=++size; ch[size][0]=ch[size][1]=0; flag[size]=0; } u=ch[u][c]; } flag[u]=1;}void build(){ queue<int>q; if(ch[0][0]) q.push(ch[0][0]); if(ch[0][1]) q.push(ch[0][1]); int r,u,v; while(!q.empty()) { r=q.front();q.pop(); for(int c=0;c<2;++c) { u=ch[r][c]; if(!u) {ch[r][c]=ch[next[r]][c];continue;} q.push(u); v=next[r]; while(v&&!ch[v][c]) v=next[v]; next[u]=ch[v][c]; flag[u]|=flag[next[u]]; } }}int f(int pos,int st,bool zero,bool limit){ if(pos==-1) return 1; if(!limit&&dp[pos][st]!=-1) return dp[pos][st]; int ans=0,u,i=0,last; if(pos>0&&zero) { ans=(ans+f(pos-1,0,true,limit&&num[pos]==0))%mod; i=1; } last=limit?num[pos]:9; for(;i<=last;++i) { u=st; for(int j=3;j>=0;--j) { u=ch[u][(i&(1<<j))!=0]; if(flag[u]) {u=-1;break;} } if(u!=-1) ans=(ans+f(pos-1,u,false,limit&&i==last))%mod; } if(!limit&&!zero) dp[pos][st]=ans; return ans;}int cal(bool d){ memset(num,0,sizeof(num)); int len=strlen(str); for(int i=0;i<len;++i) num[i]=str[len-i-1]-'0'; if(d) { num[0]--; int i=0; while(num[i]<0) { num[i++]=9; num[i]--; } if(!num[len-1]&&len!=1) len--; } return f(len-1,0,true,true);}int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int t,n; scanf("%d",&t); while(t--) { Init(); scanf("%d",&n); for(int i=0;i<n;++i) { scanf("%s",str); Insert(str); } build(); int res=0; scanf("%s",str); res-=cal(true); scanf("%s",str); res+=cal(false); res=(res%mod+mod)%mod; printf("%d\n",res); } return 0;}
0 0
- ZOJ 3494 BCD Code(AC自动机+数位DP)
- ZOJ 3494 BCD Code 数位DP+AC自动机
- ZOJ 3494 BCD Code (AC自动机+数位DP,5级)
- 【MZ】ZOJ 3494 BCD Code AC自动机+数位DP
- ZOJ 3494 BCD Code(AC自动机+数位DP)
- ZOJ 3494 BCD Code(AC自动机+数位DP)
- ZOJ 3494 BCD Code AC自动机+数位DP
- ZOJ 3494 BCD Code AC自动机+数位DP
- 【ZOJ】3494 BCD Code AC自动机+数位DP
- zoj 3494 BCD Code AC自动机+数位dp
- zoj 3494 BCD Code(AC自动机+数位dp)
- ZOJ 3494 BCD Code AC自动机 + 数位DP
- 【AC自动机+数位DP】【zoj 3494】BCD Code
- ZOJ Problem Set - 3494 BCD Code AC自动机+数位DP
- zoj 3494 BCD Code (ac自动机+数位dp)
- [AC自动机+数位dp] zoj 3494 BCD Code
- ZOJ - 3494 BCD Code(AC自动机+数位DP)
- ZOJ 3494 BCD Code (AC自动机 + 数位DP)
- java/c/c++在线编译器
- 充电的几个过程如何控制的
- 01串压缩编码
- Android 测试 Intel HAXM 超快模拟器时出现的问题解决
- Taking Photos Simply
- ZOJ 3494 BCD Code(AC自动机+数位DP)
- SAE 存取文件
- HDU 2029 Palindromes _easy version
- Unity3D物理性能优化
- HDU 1943 Ball bearings(简单计算几何)
- SOS
- 有cdh认证的
- c++学习笔记(17.专题四经典问题解析)
- JavaSE学习笔记