【BZOJ3530】【SDOI2014】—数数(Ac自动机+数位dp)

传送门


f[0/1][j][k]f[0/1][j][k]表示有无限制,匹配到jj位,在自动机上的点kk的方案数
dpdp就完了

注意前导0的情况,比如限制01230123,但123123是合法的

#include<bits/stdc++.h>
using namespace std;
#define gc getchar
inline int read(){
    char ch=gc();
    int res=0,f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
#define pb push_back
#define re register
#define cs const
#define ll long long
#define pii pair<int,int>
#define fi first
#define se second
const int mod=1e9+7;
inline int add(int a,int b){return (a+=b)>=mod?a-=mod:a;}
inline void Add(int &a,int b){(a+=b)>=mod?a-=mod:0;}
inline int dec(int a,int b){return (a-=b)<0?a+=mod:a;}
inline void Dec(int &a,int b){(a-=b)<0?a+=mod:0;}
inline int mul(int a,int b){return 1ll*a*b>=mod?1ll*a*b%mod:a*b;}
inline void Mul(int &a,int b){a=mul(a,b);}
inline int ksm(int a,int b,int res=1){
    for(;b;b>>=1,a=mul(a,a))(b&1)&&(res=mul(res,a));return res;
}
inline void chemx(int &a,int b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
const int N=1505;
namespace Ac{
    int nxt[N][11],fail[N],end[N],tot;
    inline void insert(char *s){
        int p=0;
        for(int i=1,len=strlen(s+1);i<=len;i++){
            int c=s[i]-'0';
            if(!nxt[p][c])nxt[p][c]=++tot;
            p=nxt[p][c];
        }
        end[p]++;
    }
    queue<int> q;
    inline void build(){
        for(int i=0;i<=9;i++){
            int v=nxt[0][i];
            if(v)q.push(v),fail[v]=0;
        }
        while(!q.empty()){
            int p=q.front();q.pop();
            for(int c=0;c<=9;c++){
                int v=nxt[p][c];
                if(!v)nxt[p][c]=nxt[fail[p]][c];
                else fail[v]=nxt[fail[p]][c],q.push(v);
            }
            end[p]+=end[fail[p]];
        }
    }
    int f[2][N][N];
    inline void dp(char *s){
        for(int i=1;i<s[1]-'0';i++)f[0][1][nxt[0][i]]+=1;
        f[1][1][nxt[0][s[1]-'0']]+=1;
        int len=strlen(s+1);
        for(int i=1;i<len;i++){
            for(int j=1;j<10;j++)f[0][i+1][nxt[0][j]]+=1;
            for(int j=0;j<=tot;j++){
                if(end[j])continue;
                if(f[0][i][j])for(int c=0;c<10;c++)
                    if(!end[nxt[j][c]])Add(f[0][i+1][nxt[j][c]],f[0][i][j]);
                if(f[1][i][j])for(int c=0;c<s[i+1]-'0';c++)
                    if(!end[nxt[j][c]])Add(f[0][i+1][nxt[j][c]],f[1][i][j]);
                if(!end[nxt[j][s[i+1]-'0']])
                    Add(f[1][i+1][nxt[j][s[i+1]-'0']],f[1][i][j]);
            }
        }
        int res=0;
        for(int i=0;i<=tot;i++)if(!end[i])Add(res,f[0][len][i]),Add(res,f[1][len][i]);
        cout<<res<<'
';
    }
}
int n,m;
char s[N],t[N];
int main(){
    scanf("%s",t+1);
    m=read();
    for(int i=1;i<=m;i++)
    scanf("%s",s+1),Ac::insert(s);
    Ac::build();
    Ac::dp(t);
}
原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328779.html