題意:給定的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;}