ZOJ BCD Code 记忆化搜索+数位DP+AC自动机
来源:互联网 发布:添加网络位置 ftp 编辑:程序博客网 时间:2024/06/05 03:50
题意:给定的BCD吗,当翻译十进制数时,最终形成的01串中可能有禁止出现的子串,叫我们求[a,b]中有多少个完全正确的数。
做法:对于禁止的串,直接AC自动机处理。以为a,b都是大数,所以a要先用大数减法减1。
最近不知道是不是记忆化搜索用上瘾了。。。。记录的状态是当前字符所在tire树中的位置,还有是不是数组首位,以及是不是在测层边界上的数。这个题中最首位数的处理要小心。还好只是一个RE之后就A了,本来以为可以调很久。
#include<cstdio>#include<cstring>#include<deque>#define mod 1000000009#define LL long longconst int LMT=203;const int wiz=2;const int WEI=4;using namespace std;int code[10],gra[3002][2],fail[3002],siz;bool word[3002];char num[LMT];LL dp[3002][LMT];int len;void insert(char sor[]) { int index,current =0; for(int i=0;sor[i];i++) { index=sor[i]-'0'; if(!gra[current][index])gra[current][index]=siz++; current=gra[current][index]; } word[current]|=1; } void build_ac(void) { int current,v; deque<int>q; q.clear(); for(int i=0;i<wiz;i++) if(gra[0][i])q.push_back(gra[0][i]); while(!q.empty()) { current=q.front(); q.pop_front(); for(int i=0;i<wiz;i++) if(gra[current][i]) { v=gra[current][i]; fail[v]=gra[fail[current]][i]; word[v]|=word[fail[v]]; q.push_back(v); } else gra[current][i]=gra[fail[current]][i]; } } void init(void){ siz=1; memset(word,0,sizeof(word)); memset(fail,0,sizeof(fail)); memset(gra,0,sizeof(gra));memset(dp,-1,sizeof(dp));memset(num,0,sizeof(num));}LL dfs(int node,int pos,bool tag,bool first){if(pos==-1){if(first){int tem=node;for(int j=WEI-1;j>=0&&!word[tem];j--)tem=gra[tem][0];return !word[tem];}else return !word[node];}if(dp[node][pos]!=-1&&!tag&&!first)return dp[node][pos];int i,j,x,end,tem;LL res=0;if(tag)end=num[pos];else end=9;for(i=first;i<=end;i++){x=code[i];tem=node;for(j=WEI-1;j>=0&&!word[tem];j--)tem=gra[tem][(x>>j)&1];if(word[tem])continue;res+=dfs(tem,pos-1,tag&&i==end,0);res%=mod;}if(first)res+=dfs(node,pos-1,tag&&i==end,1);if(!first&&!tag&&dp[node][pos]==-1)dp[node][pos]=res;return res;}void cut(){int i,j,c=1;char a[LMT];memset(a,0,sizeof(a));for(i=len-1,j=0;i>=0;i--,j++){a[j]=num[i];}memset(num,0,sizeof(num));for(i=0;i<LMT&&c;i++){a[i]=a[i]-c;if(a[i]<0){a[i]=9;c=1;}else c=0;}for(i=LMT-1;i>=0&&a[i]==0;i--);len=i+1;if(i<0)len=1;for(i=len-1,j=0;i>=0;i--,j++)num[j]=a[i];}int main(void){int T,i,n;char sec[25];LL a,b;for(i=0;i<10;i++)code[i]=i;scanf("%d",&T);while(T--){init();scanf("%d",&n);while(n--){scanf("%s",sec);insert(sec);}build_ac();scanf("%s",num);len=strlen(num);for(i=0;num[i];i++)num[i]-='0';cut();for(i=0;i<len>>1;i++)swap(num[i],num[len-i-1]);a=dfs(0,len-1,1,1);memset(num,0,sizeof(num));scanf("%s",num);len=strlen(num);for(i=0;i<len;i++)num[i]-='0';for(i=0;i<len>>1;i++)swap(num[i],num[len-i-1]);b=dfs(0,len-1,1,1);printf("%lld\n",(b-a+mod)%mod);}return 0;}
- ZOJ BCD Code 记忆化搜索+数位DP+AC自动机
- zoj 3494 BCD Code 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
- 【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)
- 对于4个问题的感慨
- 用母函数的思路解释母函数的代码
- 第二次实验报告
- 电脑基本技能
- 判断字符串string所有分割和子串是否为回文(palindrome)并返回结果(Palindrome Partitioning)
- ZOJ BCD Code 记忆化搜索+数位DP+AC自动机
- 比较java的arraylist和linkedlist
- HDU 1588 Gauss Fibonacci
- Lua 程序设计初步
- Html/CSS菜单代码
- usaco-1.5-总结
- 树状数组
- 获取某一天之前或者之后多少天的日期
- poj1143Number Game