题解:建立AC自动机,然后Dp
考虑长度与n相等时
f[i][j][2]表示第i位匹配到AC自动机第j号节点,是否顶着上界的方案数
转移枚举这一位填什么
注意,如果当前节点沿Fail树能走到单词节点就不能转移到他
长度<lenn不用考虑顶上界
问题:不明白最后统计答案的方式
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=2009;
const int mm=1000000007;
int n,m;
char s[maxn];
int a[maxn];
int nn;
int ch[maxn][10];
int val[maxn];
void Ins() {
int n=strlen(s);
int u=0;
for(int i=0; i<n; ++i) {
int c=s[i]-‘0‘;
if(!ch[u][c])ch[u][c]=++nn;
u=ch[u][c];
}
val[u]=1;
}
queue<int>q;
int fai[maxn];
void Getfail(){
for(int c=0;c<=9;++c){
int v=ch[0][c];
if(v)q.push(v);
}
while(!q.empty()){
int u=q.front();q.pop();
for(int c=0;c<=9;++c){
int v=ch[u][c];
if(!v)continue;
q.push(v);
val[v]|=val[u];
int j=fai[u];
while((j)&&(!ch[j][c]))j=fai[j];
fai[v]=ch[j][c];
val[v]|=val[fai[v]];
}
}
}
long long f[maxn][maxn][2];
long long ans;
int main() {
scanf("%s",s);
n=strlen(s);
for(int i=1; i<=n; ++i)a[i]=s[i-1]-‘0‘;
scanf("%d",&m);
while(m--) {
scanf("%s",s);
Ins();
}
Getfail();
memset(f,0,sizeof(f));
for(int c=1;c<=9;++c){
int v=ch[0][c];
if(val[v])continue;
if(c<a[1])f[1][v][0]++;
if(c==a[1])f[1][v][1]++;
}
for(int i=1;i<n;++i){
for(int j=0;j<=nn;++j){
for(int c=0;c<=9;++c){
int u=j;
while((u)&&(!ch[u][c]))u=fai[u];
int v=ch[u][c];
if(val[v])continue;
if(c<a[i+1]){
f[i+1][v][0]=(f[i+1][v][0]+f[i][j][0]+f[i][j][1])%mm;
}
if(c==a[i+1]){
f[i+1][v][0]=(f[i+1][v][0]+f[i][j][0])%mm;
f[i+1][v][1]=(f[i+1][v][1]+f[i][j][1])%mm;
}
if(c>a[i+1]){
f[i+1][v][0]=(f[i+1][v][0]+f[i][j][0])%mm;
}
}
}
}
for(int j=0;j<=nn;++j){
ans=(ans+f[n][j][0]+f[n][j][1])%mm;
}
// ans=(f[n][0][0]+f[n][0][1])%mm;
// for(int c=0;c<=9;++c){
// int v=ch[0][c];
// if(v){
// ans=(ans+f[n][v][0]+f[n][v][1])%mm;
// }
// }
// cout<<ans<<endl;
--n;
memset(f,0,sizeof(f));
for(int c=1;c<=9;++c){
int v=ch[0][c];
if(val[v])continue;
f[1][v][0]++;
}
for(int i=1;i<n;++i){
for(int j=0;j<=nn;++j){
for(int c=0;c<=9;++c){
int u=j;
while((u)&&(!ch[u][c]))u=fai[u];
int v=ch[u][c];
if(val[v])continue;
f[i+1][v][0]=(f[i+1][v][0]+f[i][j][0])%mm;
}
}
// ans=(ans+f[i+1][0][0])%mm;
// for(int c=0;c<=9;++c){
// int v=ch[0][c];
// if(!v)continue;
// ans=(ans+f[i+1][v][0])%mm;
// }
}
for(int i=1;i<=n;++i){
for(int j=0;j<=nn;++j){
ans=(ans+f[i][j][0])%mm;
}
}
cout<<ans<<endl;
return 0;
}