题意:给定n个串,找出[L,R]中满足条件的数的数量。条件:该数的BCD码不出现n个串中的任意一个。
题解:
搞懂了AC自动机就变得很简单
上了可计算性理论之后对AC自动机的理解:AC自动机其实就是建立一个确定性有穷自动机。任意一个输入的语言从起始节点出发,如果途经终结状态,那么它便包含AC自动机中存的子串。
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
const int mod=1000000009;
char s[25],a[205],b[205];
int dig[205];
ll d[205][2005];
struct Tire {
int Next[2005][2],fail[2005],End[2005];
int root,tot;
int newNode() {
memset(Next[tot],-1,sizeof(Next[tot]));
End[tot]=0;
return tot++;
}
void init() {
tot=0;
root=newNode();
memset(End,0,sizeof(End));
}
void insert(char *buf) {
int len=strlen(buf);
int now=root;
for(int i=0;i<len;++i) {
if(Next[now][buf[i]-'0']==-1) Next[now][buf[i]-'0']=newNode();
now=Next[now][buf[i]-'0'];
}
End[now]++;
}
void build() {
queue<int> q;
fail[root]=root;
for(int i=0;i<=1;++i) {
if(Next[root][i]==-1) {
Next[root][i]=root;
} else {
fail[Next[root][i]]=root;
q.push(Next[root][i]);
}
}
while(!q.empty()) {
int now=q.front();q.pop();
for(int i=0;i<=1;++i) {
if(Next[now][i]==-1) {
Next[now][i]=Next[fail[now]][i];
} else {
fail[Next[now][i]]=Next[fail[now]][i];
if(End[Next[fail[now]][i]]) End[Next[now][i]]=1;
q.push(Next[now][i]);
}
}
}
}
}ac;
ll dp(int po,int sta,bool zero,bool limit) {
// printf("%d %d %d\n",po,sta,pre);
if(po<0) return 1&&!zero;
if(!zero&&!limit&&d[po][sta]!=-1) return d[po][sta];
int to=limit?dig[po]:9;
ll ans=0;
for(int i=0;i<=to;++i) {
if(zero&&i==0) {
ans=(ans+dp(po-1,0,1,limit&&i==to))%mod;
} else {
int nxtsta=sta,x=i;
bool f=1;
for(int j=8;j;j>>=1) {
int bit=x/j;x=x-bit*j;
nxtsta=ac.Next[nxtsta][bit];
if(ac.End[nxtsta]) {
f=0;
break;
}
}
if(f) ans=(ans+dp(po-1,nxtsta,0,limit&&i==to))%mod;
}
}
if(!zero&&!limit) d[po][sta]=ans;
return ans;
}
ll solve(char *x) {
int po=strlen(x);
for(int i=0;i<po;++i) {
dig[i]=x[po-1-i]-'0';
}
return dp(po-1,0,1,1);
}
int main() {
int T;scanf("%d",&T);
while(T--) {
///
int n;scanf("%d",&n);
///init
ac.init();
memset(d,-1,sizeof(d));
///read
for(int i=1;i<=n;++i) {
scanf("%s",s);
ac.insert(s);
}
scanf("%s%s",a,b);
///get ac
ac.build();
///get a
int lena=strlen(a),p=lena-1;
while(a[p]=='0') {
a[p--]='9';
}
a[p]=a[p]-1;
///solve
printf("%lld\n",(solve(b)-solve(a)+mod)%mod);
}
return 0;
}