首先要建立AC自动机 然后模板串可能前面出现0 处理起来可能会有点麻烦 所以我们干脆直接把模板串倒着插入 然后在Trie中进行dp
用d[i][j][0] 表示在第i个节点 枚举到第j位 且第j位没有超过N的方案数(d[i][j][1]则为超过了
至于为什么要统计超过了的数的个数 是因为我们是从低位开始开始确定这个数的 所以之后的位数如果小于N 那么整体是不会超过N的)
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
#define SF scanf
#define PF printf
#define idx(c) (c-'0')
using namespace std;
typedef long long LL;
const int MAXNODE = 1500;
const int SZ = 10;
const int MOD = 1e9+7;
char s[MAXNODE+10], ss[MAXNODE+10];
int n;
int d[MAXNODE+10][MAXNODE+10][2+10];
struct Aho_Corasick {
int ch[MAXNODE+10][SZ+10], match[MAXNODE+10], f[MAXNODE+10];
int ncnt, zero[MAXNODE+10];
void init() { ncnt = 1; memset(ch[0], 0, sizeof(ch[0])); }
int NewNode() { memset(ch[ncnt], 0, sizeof(ch[ncnt])); return ncnt++; }
void insert(char *s) {
int n = strlen(s), u = 0;
for(int i = n-1; i >= 0; i--) {
int c = idx(s[i]);
if(!ch[u][c]) ch[u][c] = NewNode();
u = ch[u][c];
}
match[u] = 1;
if(s[0] == '0') zero[u] = 1;
}
void GetFail() {
queue<int> q;
f[0] = 0;
for(int i = 0; i < SZ; i++) {
if(!ch[0][i]) ch[0][i] = 0;
else {
q.push(ch[0][i]);
f[ch[0][i]] = 0;
}
}
while(!q.empty()) {
int u = q.front(); q.pop();
for(int i = 0; i < SZ; i++) {
if(!ch[u][i]) { ch[u][i] = ch[f[u]][i]; continue; }
q.push(ch[u][i]);
f[ch[u][i]] = ch[f[u]][i];
match[ch[u][i]] |= match[f[ch[u][i]]];
zero[ch[u][i]] |= zero[ch[u][i]];
}
}
}
void dp(int u, int cur, int over) {
int &ret = d[u][cur][over];
if(~ret) return ;
if(match[u]) {
int t = 0;
if(zero[u]) t = 1;
d[u][cur][0] = d[u][cur][1] = t;
if(!cur) d[u][cur][1] = 0;
return ;
}
if(!cur) {
d[u][cur][1] = 0; d[u][cur][0] = 1;
return ;
}
ret = 0;
for(int c = 0; c < SZ; c++) {
if(over) {
if(c >= idx(s[cur-1])) {
dp(ch[u][c], cur-1, 1);
ret = (ret + d[ch[u][c]][cur-1][1]) % MOD;
}
else {
dp(ch[u][c], cur-1, 0);
ret = (ret + d[ch[u][c]][cur-1][0]) % MOD;
}
}
else {
if(c > idx(s[cur-1])) {
dp(ch[u][c], cur-1, 1);
ret = (ret + d[ch[u][c]][cur-1][1]) % MOD;
}
else {
dp(ch[u][c], cur-1, 0);
ret = (ret + d[ch[u][c]][cur-1][0]) % MOD;
}
}
}
}
} ac;
int main() {
ac.init();
memset(d, -1, sizeof(d));
SF("%s%d", s, &n);
for(int i = 1; i <= n; i++) {
SF("%s", ss);
ac.insert(ss);
}
ac.GetFail();
int len = strlen(s);
ac.dp(0, len, 0);
PF("%d\n", d[0][len][0]-1);
}