题意
有一种BCD编码方案,求A到B范围内的数字的BCD编码有多少个不包含不能包含的字符串。
题解
数字范围这么大,很明显就能看出来是数位DP。基于AC自动机的数位DP使得数位DP容易了不少,因为AC自动机自带状态转移。在数位DP选取每一位的时候,基于AC自动机状态转移一下,如果转移到不能转移的状态,就直接返回-1。如果转移到合法状态,就继续DFS。唯一需要注意的就是需要大整数的减法,不过随便写写就行了,有前导0也无所谓,反正不影响数位DP。
代码
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<string>
#include<set>
#include<map>
#include<bitset>
#include<stack>
#include<string>
#define UP(i,l,h) for(int i=l;i<h;i++)
#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)
#define W(a) while(a)
#define MEM(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
#define MAXN 100010
#define MOD 1000000009
#define EPS 1e-10
#define int LL
using namespace std;
int ch[2010][10];
int sz;
int val[2010],f[2010];
char st[30];
int dig[220];
int dp[210][2010];
char a[210],b[210];
int code[10][4]= {{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1},{0,1,0,0},{0,1,0,1},{0,1,1,0},{0,1,1,1},{1,0,0,0},{1,0,0,1}};
int run(int u,int x) {
if(val[u]) {
return -1;
}
UP(i,0,4) {
u=ch[u][code[x][i]];
if(val[u]) {
return -1;
}
}
return u;
}
void insert() {
int u=0;
int len=strlen(st);
UP(i,0,len) {
int x=st[i]-'0';
if(!ch[u][x]) {
ch[u][x]=sz++;
}
u=ch[u][x];
}
val[u]=1;
// cout<<"u"<<u<<endl;
}
void getFail() {
MEM(f,0);
queue<int> q;
UP(i,0,10) {
if(ch[0][i]) {
q.push(ch[0][i]);
}
}
W(!q.empty()) {
int r=q.front();
q.pop();
UP(i,0,10) {
int u=ch[r][i];
if(!u) {
ch[r][i]=ch[f[r]][i];
continue;
}
q.push(u);
int v=f[r];
f[u]=ch[v][i];
val[u]|=val[f[u]];
// cout<<"val"<<u<<" "<<val[u]<<endl;
}
}
}
int dfs(int len,int u,bool first,bool up) {
if(len==0) {
if(!first)
return 1;
else
return 0;
}
if(!up&&!first&&(dp[len][u]!=-1)) {
return dp[len][u];
}
int n=up?dig[len]:9;
int ans=0;
UP(i,0,n+1) {
if(i==0&&first) {
ans=(ans+dfs(len-1,u,true,up&&i==n))%MOD;
} else {
int temp=run(u,i);
if(temp==-1) {
continue;
}
ans=(ans+dfs(len-1,temp,false,up&&i==n))%MOD;
}
}
if(!up&&!first) {
dp[len][u]=ans%MOD;
}
return ans%MOD;
}
int solve(char *x) {
MEM(dp,-1);
MEM(dig,0);
int len=strlen(x);
UP(i,0,len){
dig[len-i]=x[i]-'0';
}
return dfs(len+1,0,true,true);
}
main() {
int t;
scanf("%lld",&t);
W(t--) {
MEM(ch,0);
MEM(val,0);
sz=1;
int n;
scanf("%lld",&n);
W(n--) {
scanf("%s",st);
insert();
}
getFail();
scanf("%s%s",&a,&b);
int len=strlen(a);
DOWN(i,len,0){
if(a[i]=='0'){
a[i]='9';
}else{
a[i]--;
break;
}
}
printf("%lld\n",(solve(b)-solve(a)+MOD)%MOD);
}
}
/*
55
1
1001
1 10
*/