真实迷惑题,这个3200分不知道是怎么标上去的。
考虑计算出不是half-occurrence的串数目。把所有
s
s
s长度为
⌊
d
2
⌋
\lfloor \frac{d}{2}\rfloor
⌊2d⌋的子串插入一个AC自动机,然后对
x
x
x和
y
y
y做个数位DP即可。DP的时候需要预处理出
F
[
i
]
[
j
]
F[i][j]
F[i][j]表示当前在AC自动机上的节点
i
i
i,走
j
j
j步后仍然没有包含任何一个
s
s
s长度为
⌊
d
2
⌋
\lfloor \frac{d}{2}\rfloor
⌊2d⌋的子串的方案数,这个直接算就好了。
时间复杂度
O
(
∣
s
∣
d
2
⋅
10
)
\mathcal O(|s|d^2\cdot 10)
O(∣s∣d2⋅10)。
#include <bits/stdc++.h>
#define MOD 1000000007
using namespace std;
inline void add(int &x,int y) {
((x+=y)>=MOD)?x-=MOD:0;
}
namespace AC {
int ch[25005][10],tot=1;
bool ban[25005];
void insert(char *s,int len) {
int x=1;
for(int i=0;i<len;i++) {
int v=s[i]-'0';
if (!ch[x][v]) ch[x][v]=++tot;
x=ch[x][v];
}
ban[x]=1;
}
int fail[25005];
queue <int> q;
void bfs() {
for(int i=0;i<10;i++)
if (ch[1][i]) {
fail[ch[1][i]]=1;
q.push(ch[1][i]);
}
else ch[1][i]=1;
while (!q.empty()) {
int x=q.front();q.pop();
for(int i=0;i<10;i++)
if (ch[x][i]) {
fail[ch[x][i]]=ch[fail[x]][i];
q.push(ch[x][i]);
}
else ch[x][i]=ch[fail[x]][i];
}
}
int f[55][25005];
void dp(int n) {
for(int i=1;i<=tot;i++)
if (!ban[i]) f[0][i]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=tot;j++)
if (!ban[j]) {
for(int k=0;k<10;k++)
if (f[i-1][ch[j][k]]) add(f[i][j],f[i-1][ch[j][k]]);
}
}
}
int solve(int n,char *s) {
int x=1,ans=0;
for(int i=n;i>0;i--) {
int v=s[i]-'0';
for(int j=0;j<v;j++)
if (!AC::ban[AC::ch[x][j]]) add(ans,AC::f[i-1][AC::ch[x][j]]);
x=AC::ch[x][v];
if (AC::ban[x]) break;
}
if (!AC::ban[x]) add(ans,1);
return ans;
}
char str[1005],s1[55],s2[55];
int main() {
scanf("%s%s%s",str+1,s1+1,s2+1);
int n=strlen(str+1),m=strlen(s1+1);
reverse(s1+1,s1+m+1);
reverse(s2+1,s2+m+1);
for(int i=1;i<=n-(m>>1)+1;i++) AC::insert(str+i,m>>1);
AC::bfs();
AC::dp(m);
int d=1;
while (s1[d]=='0') d++;
s1[d]--;
for(int i=1;i<d;i++) s1[i]='9';
int ans=0,s=0;
for(int i=m;i>0;i--) s=(s*10LL+s1[i]-'0')%MOD;
ans=(ans-s+MOD)%MOD;
ans=(ans+solve(m,s1))%MOD;
s=0;
for(int i=m;i>0;i--) s=(s*10LL+s2[i]-'0')%MOD;
ans=(ans+s)%MOD;
ans=(ans-solve(m,s2)+MOD)%MOD;
printf("%d\n",ans);
return 0;
}