zoj 3494
数位dp+ac自动机
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define mod 1000000009
#define N 2010
typedef long long ll;
using namespace std;
char s[210];
int next[N][2],nextd[N][10],pos,flag[N],fail[N];
ll dp[210][N];
int newnode(){
memset(next[pos],0,sizeof(next[pos]));
memset(nextd[pos],0,sizeof(nextd[pos]));
flag[pos]=fail[pos]=0;
return pos++;
}
void insert(){
int p=0,i;
for(i=0;s[i];i++){
int k=s[i]-'0';
p=next[p][k]?next[p][k]:next[p][k]=newnode();
}
flag[p]=1;
}
void makefail(){
queue<int>q;
q.push(0);
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=0;i<2;i++){
int v=next[u][i];
if(v==0) next[u][i]=next[fail[u]][i];
else q.push(v);
if(u&&v){
fail[v]=next[fail[u]][i];
flag[v]|=flag[fail[v]];
}
}
}
}
void makenext(){
int tem,i,j,k;
for(i=0;i<pos;i++){
for(j=0;j<10;j++){
if(flag[i]==0){
tem=i; //在这wa死了
for(k=3;k>=0;k--){ //在这wa死了
if(j&(1<<k)){
tem=next[tem][1];
}
else{
tem=next[tem][0];
}
if(flag[tem]==1)break;
}
if(k==-1) nextd[i][j]=tem;
else nextd[i][j]=-1;
}
else nextd[i][j]=-1;
}
}
}
void pre(){
int len=strlen(s),i,j;
for(i=0;i<len;i++) if(s[i]!='0')break;
if(i==0)return;
for(j=i,i=0;j<len;j++,i++) s[i]=s[j];
s[i]='\0';
}
void minus_one(){
int len=strlen(s),i;
for(i=len-1;i>=0;i--){
if(s[i]>'0'){
s[i]--;
return ;
}
else s[i]='9';
}
}
/*ll dfs(int pos,int sta,int pre,int doing){ //不需要存储前面都是0的解,因为只会用到一次,dp少开一维
if(!s[pos]) return 1;
if(!doing && pre && dp[pos][sta]!=-1) return dp[pos][sta];
ll ans=0;
int i,end;
if(doing)end=s[pos]-'0'; else end=9;
if(pre==0) ans=dfs(pos+1,0,0,0)%mod;
else{
if(nextd[sta][0]!=-1) ans=(ans+dfs(pos+1,nextd[sta][0],1,(doing && (i==end))))%mod;
}
for(i=1;i<=end;i++){
if(nextd[sta][i]==-1)continue;
ans=(ans+dfs(pos+1,nextd[sta][i],1,(doing && (i==end))))%mod;
}
if(!doing && pre){
dp[pos][sta]=ans;
}
return ans;
}
ll solve(){
memset(dp,-1,sizeof(dp));
return dfs(0,0,0,1);
}*/
ll dfs(int pos,int sta,int first,int doing){
if(!s[pos]) return 1;
if(!doing && !first && dp[pos][sta]!=-1) return dp[pos][sta];
ll ans=0;
int i,end;
if(doing)end=s[pos]-'0'; else end=9;
for(i=first;i<=end;i++){
if(nextd[sta][i]==-1)continue;
//ans=(ans+dfs(pos+1,nextd[sta][i],0,(doing && (i==end))))%mod;
ans+=dfs(pos+1,nextd[sta][i],0,(doing && (i==end)));
if(ans>=mod)ans-=mod;
}
if(!doing && !first){
dp[pos][sta]=ans;
}
return ans;
}
ll solve(){
ll ans=0;
memset(dp,-1,sizeof(dp));
for(int i=0;s[i];i++){ //这样写是枚举长度,注意这里没有算上0
//ans=(ans+dfs(i,0,1,i==0))%mod;
ans+=dfs(i,0,1,i==0);
if(ans>=mod) ans-=mod;
}
return ans;
}
int main(){
int t,T,n,i,j;
scanf("%d",&T);
for(t=1;t<=T;t++){
scanf("%d",&n);
pos=0,newnode();
for(i=1;i<=n;i++){
scanf("%s",s);
insert();
}
makefail();
makenext();
scanf("%s",s);
pre();
minus_one();
ll ans1=solve();
scanf("%s",s);
pre();
ll ans2=solve();
printf("%lld\n",(ans2-ans1+mod)%mod);
}
return 0;
}

浙公网安备 33010602011771号