zoukankan      html  css  js  c++  java
  • 【CF585F】Digits of Number Pi(AC自动机上数位DP)

    点此看题面

    • 给定一个长为(n)的字符串(s)和两个长为(d)的字符串(l,r)
    • 问有多少长为(d)的在([l,r])内的字符串,满足存在长度至少为(lfloorfrac d2 floor)的子串是(s)的子串。
    • (nle10^3,dle50)

    (AC)自动机上数位(DP)

    如果我们把(s)每个长度为(lfloorfrac d2 floor)的子串都取出来建一个(AC)自动机,那么我们就是要求有多少个([l,r])内的字符串能匹配到至少一个模式串。

    于是就设(f_{x,rt,0/1,0/1})表示做到第(x)个字符、对应(AC)自动机上编号为(rt)的节点、是否完成过匹配、是否卡到数字上界的方案数。

    转移就枚举一下填什么字符,还是比较简单的一题。

    代码:(O(10nd^2))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 1000
    #define D 50
    #define X 1000000007
    #define Inc(x,y) ((x+=(y))>=X&&(x-=X))
    using namespace std;
    int n,d;char s[N+5],l[D+5],r[D+5];
    namespace AcAutomation//AC自动机
    {
    	int Nt=1;struct node {int P,F,S[30];}O[N*D+5];
    	I void Ins(CI x,CI y)//插入子串[l,r]
    	{
    		RI t,k=1;for(RI i=x;i<=y;k=O[k].S[t],++i)
    			!O[k].S[t=s[i]&15]&&(O[k].S[t]=++Nt);O[k].P=1;//给结尾打上标记
    	}
    	int q[N*D+5];I void Build()//建AC自动机
    	{
    		RI i,k,H=1,T=1;for(i=0;i<=9;++i)
    			(O[1].S[i]?O[q[++T]=O[1].S[i]].F:O[1].S[i])=1;
    		W(H<=T) for(k=q[H++],i=0;i<=9;++i)
    			(O[k].S[i]?O[q[++T]=O[k].S[i]].F:O[k].S[i])=O[O[k].F].S[i];
    	}
    	int f[D+5][N*D+5][2];I int DP(char *w,CI x=1,CI rt=1,CI p=0,CI fg=0)//数位DP
    	{
    		if(x>d) return p;if(fg&&~f[x][rt][p]) return f[x][rt][p];//边界;记忆化
    		RI i,k,t=0,lim=fg?9:(w[x]&15);for(i=0;i<=lim;++i)//枚举填谁
    			k=O[rt].S[i],Inc(t,DP(w,x+1,k,p||O[k].P,fg||i^lim));//更新状态
    		return fg&&(f[x][rt][p]=t),t;//记忆化
    	}
    }
    int main()
    {
    	using namespace AcAutomation;memset(f,-1,sizeof(f));
    	RI i;scanf("%s%s%s",s+1,l+1,r+1),n=strlen(s+1),d=strlen(l+1);
    	for(i=1;i<=n-(d>>1)+1;++i) Ins(i,i+(d>>1)-1);Build();//取出所有长d/2的子串建AC自动机
    	for(i=d;l[i]=='0';--i) l[i]='9';--l[i];return printf("%d
    ",(DP(r)-DP(l)+X)%X),0;//差分
    }
    
  • 相关阅读:
    SpringCloud_组件常用注解
    SpringBoot_启动器
    SICP习题 1.5 (应用序与正则序)
    SICP习题 1.4 ( if 语句返回运算符)
    SICP习题 1.3 (求较大两个数的递归)
    SICP习题 1.2 (前缀表达式)
    SICP习题 1.1 (if cond语句)
    MySQL5.7 踩坑实录
    类找不到总结java.lang.ClassNotFoundException
    网易校招2018----题目3----字符串碎片
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/CF585F.html
Copyright © 2011-2022 走看看