ZOJ 3494 AC自动机+数位DP
来源:互联网 发布:怎么刷新微信运动数据 编辑:程序博客网 时间:2024/05/22 11:35
题意
有一种BCD编码方案,求A到B范围内的数字的BCD编码有多少个不包含不能包含的字符串。
题解
数字范围这么大,很明显就能看出来是数位DP。基于AC自动机的数位DP使得数位DP容易了不少,因为AC自动机自带状态转移。在数位DP选取每一位的时候,基于AC自动机状态转移一下,如果转移到不能转移的状态,就直接返回-1。如果转移到合法状态,就继续DFS。唯一需要注意的就是需要大整数的减法,不过随便写写就行了,有前导0也无所谓,反正不影响数位DP。
代码
#include <iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<string>#include<set>#include<map>#include<bitset>#include<stack>#include<string>#define UP(i,l,h) for(int i=l;i<h;i++)#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)#define W(a) while(a)#define MEM(a,b) memset(a,b,sizeof(a))#define INF 0x3f3f3f3f#define LL long long#define MAXN 100010#define MOD 1000000009#define EPS 1e-10#define int LLusing namespace std;int ch[2010][10];int sz;int val[2010],f[2010];char st[30];int dig[220];int dp[210][2010];char a[210],b[210];int code[10][4]= {{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1},{0,1,0,0},{0,1,0,1},{0,1,1,0},{0,1,1,1},{1,0,0,0},{1,0,0,1}};int run(int u,int x) { if(val[u]) { return -1; } UP(i,0,4) { u=ch[u][code[x][i]]; if(val[u]) { return -1; } } return u;}void insert() { int u=0; int len=strlen(st); UP(i,0,len) { int x=st[i]-'0'; if(!ch[u][x]) { ch[u][x]=sz++; } u=ch[u][x]; } val[u]=1;// cout<<"u"<<u<<endl;}void getFail() { MEM(f,0); queue<int> q; UP(i,0,10) { if(ch[0][i]) { q.push(ch[0][i]); } } W(!q.empty()) { int r=q.front(); q.pop(); UP(i,0,10) { int u=ch[r][i]; if(!u) { ch[r][i]=ch[f[r]][i]; continue; } q.push(u); int v=f[r]; f[u]=ch[v][i]; val[u]|=val[f[u]];// cout<<"val"<<u<<" "<<val[u]<<endl; } }}int dfs(int len,int u,bool first,bool up) { if(len==0) { if(!first) return 1; else return 0; } if(!up&&!first&&(dp[len][u]!=-1)) { return dp[len][u]; } int n=up?dig[len]:9; int ans=0; UP(i,0,n+1) { if(i==0&&first) { ans=(ans+dfs(len-1,u,true,up&&i==n))%MOD; } else { int temp=run(u,i); if(temp==-1) { continue; } ans=(ans+dfs(len-1,temp,false,up&&i==n))%MOD; } } if(!up&&!first) { dp[len][u]=ans%MOD; } return ans%MOD;}int solve(char *x) { MEM(dp,-1); MEM(dig,0); int len=strlen(x); UP(i,0,len){ dig[len-i]=x[i]-'0'; } return dfs(len+1,0,true,true);}main() { int t; scanf("%lld",&t); W(t--) { MEM(ch,0); MEM(val,0); sz=1; int n; scanf("%lld",&n); W(n--) { scanf("%s",st); insert(); } getFail(); scanf("%s%s",&a,&b); int len=strlen(a); DOWN(i,len,0){ if(a[i]=='0'){ a[i]='9'; }else{ a[i]--; break; } } printf("%lld\n",(solve(b)-solve(a)+MOD)%MOD); }}/*55110011 10*/
阅读全文
0 0
- zoj 3494(ac自动机+数位dp)
- ZOJ 3494 AC自动机+数位DP
- 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
- 打造一个简单的Java字节码反编译器
- 深入剖析Nginx时间缓存
- 最大化平均值
- 离线下载(MainActivity)
- XML 新手入门基础知识
- ZOJ 3494 AC自动机+数位DP
- 简易Vector
- 基于string的undered_map的实现
- string 一些
- mybatis查询缓存
- 对类的理解
- 数据结构和算法分析之排序篇--归并排序(Merge Sort)和常用排序算法时间复杂度比较(附赠记忆方法)
- 课程大纲
- android学习1----创建项目并且通过xml设计layout