zoukankan      html  css  js  c++  java
  • 3530: [Sdoi2014]数数

    3530: [Sdoi2014]数数

    链接

    分析:

      对给定的串建立AC自动机,然后数位dp。数位dp的过程中,记录当前在AC自动机的哪个点上,保证不能走到出现了给定串的点。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<cctype>
    #include<set>
    #include<queue>
    #include<vector>
    #include<map>
    using namespace std;
    typedef long long LL;
    
    inline int read() {
        int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    
    const int N = 2005, mod = 1e9 + 7;
    int ch[N][10], q[N], fail[N], last[N], val[N], dp[N][N], Index;
    char s[N], t[N];
    
    void Insert(char *s) {
        int len = strlen(s), u = 0;
        for (int i = 0; i < len; ++i) {
            int c = s[i] - '0';
            if (!ch[u][c]) ch[u][c] = ++Index;
            u = ch[u][c];
        }
        val[u] = 1;
    }
    void bfs() {
        int L = 1, R = 0;
        for (int i = 0; i < 10; ++i) 
            if (ch[0][i]) q[++R] = ch[0][i];
        while (L <= R) {
            int u = q[L ++];
            for (int c = 0; c < 10; ++c) {
                int v = ch[u][c];
                if (!v) ch[u][c] = ch[fail[u]][c];
                else fail[v] = ch[fail[u]][c], last[v] = val[fail[v]] ? fail[v] : last[fail[v]], q[++R] = v;
            }
        }
    }
    int dfs(int pos,int now,bool lim,bool fir) { // 从高位数第pos位,在AC自动机上的位置,是否有小于n的限制,是否有前导0的限制 
        if (pos == 0) return 1;
        if (!lim && !fir && dp[pos][now] != -1) return dp[pos][now];
        int res = 0, u = lim ? (s[pos] - '0') : 9;
        if (fir) res = (res + dfs(pos - 1, 0, lim && 0 == u, 1)) % mod; // 如果当前依然没有出现第一个正整数作为开始,那么继续从0号点开始走,不能是ch[0][0]!!! 
        for (int i = fir; i <= u; ++i) {
            int v = ch[now][i];
            if (val[v] || last[v]) continue; // last表示从当前点沿着fail指针跳的过程中,第一个是给定串的点 
            res = (res + dfs(pos - 1, v, lim && i == u , 0)) % mod;
        }
        if (!lim && !fir) dp[pos][now] = res;
        return res;
    }
    int main() {
        scanf("%s", s + 1);
        int n = strlen(s + 1);
        reverse(s + 1, s + n + 1);
        int m = read();
        for (int i = 1; i <= m; ++i) {
            scanf("%s", t);
            Insert(t);
        }
        bfs();
        memset(dp, -1, sizeof(dp));
        cout << (dfs(n, 0, 1, 1) - 1 + mod) % mod;
        return 0;
    }
  • 相关阅读:
    BZOJ_3171_[Tjoi2013]循环格_最小费用最大流
    BZOJ_1150_[CTSC2007]数据备份Backup_堆+贪心
    BZOJ_1576_[Usaco2009 Jan]安全路经Travel&&BZOJ_3694_最短路_树链剖分+线段树
    BZOJ_4802_欧拉函数_MR+pollard rho+欧拉函数
    BZOJ_3667_Rabin-Miller算法_Mille_Rabin+Pollard rho
    BZOJ_1584_[Usaco2009 Mar]Cleaning Up 打扫卫生_DP
    BZOJ_1229_[USACO2008 Nov]toy 玩具_三分+贪心
    BZOJ_2160_拉拉队排练_manacher
    [转载]Linux软件包及dpkgapt等方法
    服务器基础认知杂谈及一小点运维相关
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10526404.html
Copyright © 2011-2022 走看看