您的位置:首页 > 其它

ZOJ 3494 BCD Code - AC自动机 - 数位dp

2018-02-08 11:23 417 查看
没有传送门

没有题目大意

AC自动机维护数位dp模板题

从一位神犇那里get到了一中不特判前导0姿势

我真是愚蠢晚期

真是愚蠢晚期

愚蠢晚期

晚期

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#define mod 1000000009
#define N 110
#define LEN 210
#define TN 2010
#define toi(c) (c-'0')
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
struct ac_node{
int ch[2],fail;bool val;
}t[TN];int ac_node_cnt;
char A[LEN],B[LEN];bool ban[TN];
int a[LEN],b[LEN],dp[LEN][TN][2];
int can[TN][15],f[LEN][TN];
inline int new_ac_node()
{
int x=++ac_node_cnt;t[x].fail=0,t[x].val=0;
return t[x].ch[0]=t[x].ch[1]=0,ac_node_cnt;
}
inline int solve(int x,int a)
{
if(ban[x]) return 0;
for(int i=3;i>=0;i--)
{
x=t[x].ch[(a&(1<<i))>>i];
if(ban[x]) return 0;
}
return x;
}
inline int get_can(int m)
{
for(int i=1;i<=m;i++)
for(int j=0;j<=9;j++)
can[i][j]=solve(i,j);
return 0;
}
inline int init_f(int n)
{
int m=ac_node_cnt;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
f[i][j]=0;
for(int i=1,y;i<=9;i++)
if((y=can[1][i])) f[1][y]++;
for(int i=1;i<n;i++)
for(int j=1;j<=m;j++)
if(!ban[j]&&f[i][j])
for(int k=0,y;k<=9;k++)
if((y=can[j][k]))
(f[i+1][y]+=f[i][j])%=mod;
return 0;
}
inline int get_ans(int *a,int n)
{
//  for(int i=1;i<=n;i++) cout<<a[i];cout<<endl;
if(!n) return 0;
int m=ac_node_cnt,ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) dp[i][j][0]=dp[i][j][1]=0;
for(int i=1,y;i<=a[1];i++)
if((y=can[1][i]))
dp[1][y][i==a[1]]++;
for(int i=1,y;i<n;i++)
for(int x=1;x<=m;x++)
if(!ban[x]) for(int j=0;j<=9;j++)
if((y=can[x][j]))
{
if(dp[i][x][0]) (dp[i+1][y][0]+=dp[i][x][0])%=mod;//,debug(i)sp,debug(x)sp,debug(i+1)sp,debug(y)ln;
if(dp[i][x][1]&&j<=a[i+1]) (dp[i+1][y][j==a[i+1]]+=dp[i][x][1])%=mod;//,debug(i)sp,debug(x)sp,debug(i+1)sp,debug(y)sp,debug((j==a[i+1]))ln;
}
/*  for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
debug(i)sp,debug(j)sp,debug(dp[i][j][0])sp,debug(dp[i][j][1])ln;*/
for(int i=1;i<=m;i++)
if(!ban[i]) (ans+=dp
[i][0])%=mod,(ans+=dp
[i][1])%=mod;
/*  for(int i=1;i<n;i++)
for(int j=1;j<=m;j++)
debug(i)sp,debug(j)sp,debug(f[i][j])ln;*/
for(int i=1;i<n;i++)
for(int j=1;j<=m;j++)
if(!ban[j]) (ans+=f[i][j])%=mod;
return ans;
}
inline int insert_ac(int rt,char *s,int n)
{
int x=rt;
for(int i=1;i<=n;i++)
{
int c=toi(s[i]);
if(!t[x].ch[c]) t[x].ch[c]=new_ac_node();
x=t[x].ch[c];
}
t[x].val=true;return 0;
}
queue<int> q;
struct edges{
int to,pre;
}e[TN<<1];int etop,h[TN];
inline int add_edge(int u,int v)
{
return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop;
}
inline int get_fail(int rt)
{
while(!q.empty()) q.pop();
for(int i=0;i<=1;i++)
{
int &x=t[rt].ch[i];
if(x) t[x].fail=rt,q.push(x),add_edge(rt,x);
else x=rt;
}
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=0;i<=1;i++)
{
int &y=t[x].ch[i],f=t[x].fail,c=t[f].ch[i];
if(y) t[y].fail=c,q.push(y),add_edge(c,y);
else y=c;
}
}
/*  for(int i=1;i<=ac_node_cnt;i++)
debug(i)sp,debug(t[i].ch[0])sp,debug(t[i].ch[1])ln;*/
return 0;
}
inline int get_ban(int x,bool flag)
{
for(int i=h[x];i;i=e[i].pre)
get_ban(e[i].to,flag|t[e[i].to].val);
return ban[x]=flag;
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
int x,n,al,bl,rt;scanf("%d",&n);
ac_node_cnt=0,rt=new_ac_node();
for(int i=1;i<=n;i++)
scanf("%s",A+1),insert_ac(rt,A,(int)strlen(A+1));
memset(h,0,sizeof(h)),etop=0;
get_fail(rt),get_ban(rt,false),scanf("%s%s",A+1,B+1);
al=(int)strlen(A+1),bl=(int)strlen(B+1);
for(int i=1;i<=al;i++) a[i]=A[i]-'0';
for(int i=1;i<=bl;i++) b[i]=B[i]-'0';
a[x=al]--;while(a[x]<0) a[x]+=10,a[--x]--;
if(!a[1])
{
for(int i=2;i<=al;i++) a[i-1]=a[i];
al--;
}
get_can(ac_node_cnt),init_f(max(al,bl));
printf("%d\n",(get_ans(b,bl)-get_ans(a,al)+mod)%mod);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: