- 题意:问有多少个<=n(101201)的数满足下面所给的模式串没有在其中出现过
- 思路:首先一堆串没在构造的串中,套路就是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];
}
}
}
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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人