BZOJ 3530: [Sdoi2014]数数 AC自动机+dp
思路不难,但是细节还是挺多的,要格外注意一下.
code:
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#define N 2005
#define ll long long
#define mod 1000000007
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
queue<int>q;
char str[N],S[N];
int n,m,tot,ch[N][10],f[N],dp[N][N][2],tag[N];
void insert()
{
int i,j,len=strlen(str+1),p=0;
for(i=1;i<=len;++i)
{
if(!ch[p][str[i]-'0']) ch[p][str[i]-'0']=++tot;
p=ch[p][str[i]-'0'];
}
tag[p]=1;
}
void build()
{
int i,j;
for(i=0;i<10;++i) if(ch[0][i]) q.push(ch[0][i]);
while(!q.empty())
{
int u=q.front();q.pop();
tag[u]|=tag[f[u]];
for(i=0;i<10;++i)
{
int qr=ch[u][i];
if(!qr) { ch[u][i]=ch[f[u]][i]; continue; }
f[qr]=ch[f[u]][i];
q.push(qr);
}
}
}
int main()
{
// setIO("input");
int i,j;
scanf("%s%d",S+1,&m);
n=strlen(S+1);
for(i=1;i<=m;++i) scanf("%s",str+1),insert();
build();
for(i=1;i<S[1]-'0';++i) if(!tag[ch[0][i]]) dp[1][ch[0][i]][0]+=1;
if(!tag[ch[0][S[1]-'0']]) dp[1][ch[0][S[1]-'0']][1]=1;
for(i=1;i<n;++i)
{
for(j=1;j<10;++j) if(!tag[ch[0][j]]) dp[i+1][ch[0][j]][0]+=1;
for(j=0;j<=tot;++j)
{
if(tag[j]) continue;
if(dp[i][j][0])
{
for(int k=0;k<10;++k)
{
if(tag[ch[j][k]]) continue;
(dp[i+1][ch[j][k]][0]+=dp[i][j][0])%=mod;
}
}
if(dp[i][j][1])
{
for(int k=0;k<S[i+1]-'0';++k)
{
if(tag[ch[j][k]]) continue;
(dp[i+1][ch[j][k]][0]+=dp[i][j][1]);
}
}
if(tag[ch[j][S[i+1]-'0']]) continue;
dp[i+1][ch[j][S[i+1]-'0']][1]|=dp[i][j][1];
}
}
int ans=0;
for(i=0;i<=tot;++i)
{
if(tag[i]) continue;
(ans+=dp[n][i][0])%=mod;
(ans+=dp[n][i][1])%=mod;
}
printf("%d\n",ans);
return 0;
}

浙公网安备 33010602011771号