- 题意:问有多少个<=n(\(10^{1201}\))的数满足下面所给的模式串没有在其中出现过
- 思路:首先一堆串没在构造的串中,套路就是AC自动机上dp,不经过cnt[]>0的点。
不过<=n怎么做呢?从n范围容易想到数位dp。
不过有一种更巧妙的方法:
首先位数<n,每位没有限制
(类似康托展开:每次讨论每一位取值,值<n[i]就后面的位没有限制,如果=n[i],就发现前i位固定下来了,所以我们维护的指针也往go[u][n[i]]走一位……)
ps.处理前导零
因此状态需要:\(dp[i][j]\):从\(j\)点走\(i\)步可以构成串的方案数。也很好转移。
- code:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
const int mod=1e9+7;
typedef long long ll;
char s[N],a[N];
int n;
struct AC {
int go[N][11],nd,cnt[N],fail[N];
ll dp[1999][2005];
void Insert() {
int sz=strlen(s),u=0;
for(int i=0;i<sz;i++) {
int x=s[i]-'0';
if(!go[u][x]) go[u][x]=++nd;
u=go[u][x];
}
cnt[u]++;
}
int Q[N],hd,tl;
AC() {nd=tl=0;hd=1;}
void gt_fail() {
for(int i=0;i<=9;i++) if(go[0][i])Q[++tl]=go[0][i];
while(hd<=tl) {
int u=Q[hd++];cnt[u]+=cnt[fail[u]];
for(int i=0;i<=9;i++) {
if(go[u][i])fail[go[u][i]]=go[fail[u]][i],Q[++tl]=go[u][i];
else go[u][i]=go[fail[u]][i];
// printf("%d %d: %d\n",u,i,go[u][i]);
}
}
}
void DP() {
for(int j=0;j<=nd;j++) dp[0][j]=(!cnt[j]);
for(int i=1;i<n;i++) {
for(int j=0;j<=nd;j++) {
if(cnt[j]) {continue;}
for(int x=0;x<10;x++) {
int y=go[j][x];
dp[i][j]=(dp[i][j]+dp[i-1][y])%mod;
}
}
}
}
void solve() {
DP();
ll ans=0;int u=0;
for(int x=1;x<10;x++) {
int y=go[0][x];
for(int i=0;i<n-1;i++) ans=(ans+dp[i][y])%mod;
}
for(int i=1;i<=n;i++) {
int x=a[i]-'0';
for(int c=(i==1);c<x;c++) {
int j=go[u][c];
ans=(ans+dp[n-i][j])%mod;
}
u=go[u][x];
if(cnt[u])break;
}
printf("%lld",(ans+!cnt[u])%mod);
}
}A;
int main() {
scanf("%s",a+1);n=strlen(a+1);
int m;scanf("%d",&m);
for(int i=1;i<=m;i++)scanf("%s",s),A.Insert();
A.gt_fail();
A.solve();
return 0;
}