題解 CF585F 【Digits of Number Pi】
阿新 • • 發佈:2020-07-15
考慮用數位 \(DP\) 來統計數字串個數,用 \(SAM\) 來實現子串的匹配。
設狀態 \(f(pos,cur,lenth,lim,flag)\),表示數位的位數,在 \(SAM\) 上的節點,匹配的長度,是否有最高位限制,是否已經滿足要求。
在 \(dfs\) 轉移時,若當前節點能接著匹配列舉到的字元,就直接轉移,若不能,則在 \(Parent\) 樹上向上跳,直到能接著匹配,轉移過程中判斷是否滿足條件即可。
\(code:\)
#include<bits/stdc++.h> #define maxn 2010 #define maxd 55 #define mod 1000000007 using namespace std; template<typename T> inline void read(T &x) { x=0;char c=getchar();bool flag=false; while(!isdigit(c)){if(c=='-')flag=true;c=getchar();} while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();} if(flag)x=-x; } int n,d,tot=1,las=1,root=1,cnt; int fa[maxn],len[maxn],ch[maxn][12],num[maxn],f[maxd][maxn][maxd][2][2]; char s[maxn],a[maxn],b[maxn]; void insert(int c) { int p=las,np=las=++tot; len[np]=len[p]+1; while(p&&!ch[p][c]) ch[p][c]=np,p=fa[p]; if(!p) fa[np]=root; else { int q=ch[p][c]; if(len[q]==len[p]+1) fa[np]=q; else { int nq=++tot; memcpy(ch[nq],ch[q],sizeof(ch[q])); len[nq]=len[p]+1,fa[nq]=fa[q],fa[np]=fa[q]=nq; while(ch[p][c]==q) ch[p][c]=nq,p=fa[p]; } } } int dp(int pos,int cur,int lenth,bool lim,bool flag) { if(pos==cnt+1) return flag; if(f[pos][cur][lenth][lim][flag]!=-1) return f[pos][cur][lenth][lim][flag]; int v=0,ma=9; if(lim) ma=num[pos]; for(int c=0;c<=ma;++c) { if(flag) v=(v+dp(pos+1,cur,lenth,lim&&c==ma,1))%mod; else { int p=cur; if(ch[p][c]) v=(v+dp(pos+1,ch[p][c],lenth+1,lim&&c==ma,lenth+1>=d/2))%mod; else { while(p&&!ch[p][c]) p=fa[p]; if(p) v=(v+dp(pos+1,ch[p][c],len[p]+1,lim&&c==ma,len[p]+1>=d/2))%mod; else v=(v+dp(pos+1,root,0,lim&&c==ma,0))%mod; } } } return f[pos][cur][lenth][lim][flag]=v; } int solve(char *s) { cnt=strlen(s+1),memset(f,-1,sizeof(f)); for(int i=1;i<=cnt;++i) num[i]=s[i]-'0'; return dp(1,root,0,1,0); } int main() { scanf("%s%s%s",s+1,a+1,b+1),n=strlen(s+1),d=cnt=strlen(a+1),a[cnt--]--; for(int i=1;i<=n;++i) insert(s[i]-'0'); while(a[cnt]-'0'==-1) a[cnt]--,a[cnt--]=9+'0'; printf("%d",(solve(b)-solve(a)+mod)%mod); return 0; }