对01串建立ac自动机,数位dp的状态即为ac自动机的节点。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<ostream>
#include<istream>
#include<algorithm>
#include<queue>
#include<string>
#include<cmath>
#include<set>
#include<map>
#include<stack>
#include<vector>
#define fi first
#define se second
#define ll long long
#define pii pair<int,ll>
#define P pair<int,int>
#define inf (1ll<<60)
#define eps 1e-8
#define pb push_back
using namespace std;
const int maxn=110005;
const ll mod=1000000009;
char yy[10][10];
ll dp[205][10005][2];
int n;
char l[205],r[205];
char str[205];
int ch[maxn][2];
int val[maxn];
int fail[maxn];
int sz;
struct AC
{
void init()
{
sz=1;
memset(ch[0],0,sizeof(ch[0]));
}
void insert(char* s)
{
int len=strlen(s);
int u=0;
for(int i=0; i<len; i++)
{
int v=s[i]-'0';
if(ch[u][v]==0)
{
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[u][v]=sz++;
}
u=ch[u][v];
}
val[u]=1;
}
void build()
{
queue<int>que;
for(int i=0; i<2; i++)
{
if(ch[0][i]==0)
ch[0][i]=0;
else
{
fail[ch[0][i]]=0;
que.push(ch[0][i]);
}
}
while(!que.empty())
{
int u=que.front();
que.pop();
for(int i=0; i<2; i++)
{
if(ch[u][i]==0)
ch[u][i]=ch[fail[u]][i];
else
{
fail[ch[u][i]]=ch[fail[u]][i];
que.push(ch[u][i]);
}
}
}
}
int go(char* s,int st)
{
int u=st;
int len=strlen(s);
for(int i=0;i<len;i++) {
u=ch[u][s[i]-'0'];
int tmp=u;
while(tmp) {
if(val[tmp]==1)
return -1;
tmp=fail[tmp];
}
}
return u;
}
bool query(char* s)
{
int len=strlen(s);
int u=0;
for(int i=0;i<len;i++) {
for(int j=0;j<4;j++) {
u=ch[u][yy[s[i]-'0'][j]-'0'];
int tmp=u;
while(tmp) {
if(val[tmp])
return 1;
tmp=fail[tmp];
}
}
}
return 0;
}
}ac;
ll dfs(int pos,int st,int one,int flag,char* s)
{
if(pos==-1) return 1;
if(dp[pos][st][one]!=-1 && !flag) return dp[pos][st][one];
ll ans=0;
int mx=flag?(s[pos]-'0'):9;
for(int i=0;i<=mx;i++) {
if(one && i==0) {
ans=(ans+dfs(pos-1,0,1,0,s))%mod;
continue;
}
int k=ac.go(yy[i],st);
if(k!=-1) {
ans=(ans+dfs(pos-1,k,0,flag&&i==mx,s))%mod;
}
}
if(!flag)
dp[pos][st][one]=ans;
return ans;
}
ll cal(char* s)
{
memset(dp,-1,sizeof(dp));
int l=strlen(s);
return dfs(l-1,0,1,1,s);
}
void pre()
{
for(int i=0;i<10;i++) {
switch(i) {
case(0):
yy[i][0]='0';
yy[i][1]='0';
yy[i][2]='0';
yy[i][3]='0';
yy[i][4]='\0';
break;
case(1):
yy[i][0]='0';
yy[i][1]='0';
yy[i][2]='0';
yy[i][3]='1';
yy[i][4]='\0';
break;
case(2):
yy[i][0]='0';
yy[i][1]='0';
yy[i][2]='1';
yy[i][3]='0';
yy[i][4]='\0';
break;
case(3):
yy[i][0]='0';
yy[i][1]='0';
yy[i][2]='1';
yy[i][3]='1';
yy[i][4]='\0';
break;
case(4):
yy[i][0]='0';
yy[i][1]='1';
yy[i][2]='0';
yy[i][3]='0';
yy[i][4]='\0';
break;
case(5):
yy[i][0]='0';
yy[i][1]='1';
yy[i][2]='0';
yy[i][3]='1';
yy[i][4]='\0';
break;
case(6):
yy[i][0]='0';
yy[i][1]='1';
yy[i][2]='1';
yy[i][3]='0';
yy[i][4]='\0';
break;
case(7):
yy[i][0]='0';
yy[i][1]='1';
yy[i][2]='1';
yy[i][3]='1';
yy[i][4]='\0';
break;
case(8):
yy[i][0]='1';
yy[i][1]='0';
yy[i][2]='0';
yy[i][3]='0';
yy[i][4]='\0';
break;
case(9):
yy[i][0]='1';
yy[i][1]='0';
yy[i][2]='0';
yy[i][3]='1';
yy[i][4]='\0';
break;
}
}
}
int main()
{
pre();
int t;
scanf("%d",&t);
while(t--) {
ac.init();
scanf("%d",&n);
for(int i=0;i<n;i++) {
scanf("%s",str);
ac.insert(str);
}
ac.build();
scanf("%s%s",l,r);
bool f=ac.query(l);
for(int i=0,j=strlen(l)-1;i<j;i++,j--)
swap(l[i],l[j]);
for(int i=0,j=strlen(r)-1;i<j;i++,j--)
swap(r[i],r[j]);
ll ans=(cal(r)-cal(l)+mod)%mod;
if(!f) ans=(ans+1)%mod;
printf("%lld\n",ans);
}
return 0;
}