zoukankan      html  css  js  c++  java
  • bzoj1009 KMP+矩阵dp

    https://www.lydsy.com/JudgeOnline/problem.php?id=1009

     阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字。
    他的不吉利数学A1A2...Am(0<=Ai<=9)有M位,不出现是指X1X2...Xn中没有恰好一段等于A1A2...Am. A1和X1可以为
    0
    题意

    KMP我会,矩乘dp我也会,组合起来原本应该是双倍的快乐,为什么会这样(>﹏<)

    看起来很像是一道AC自动机(KMP)的题目,N,M的数据范围很像快速矩阵幂,这就触及到我的知识盲区了

    事实上确实如此,我们考虑一个最裸的线性dp

    dp[i][j]表示这个串的前i位匹配到前j个字符的种数

    对于每一位的递推事实上可以通过枚举0到9找到之后的最大匹配,从前面开始递推出答案。

    找到最大匹配可以用kmp的next数组加速一下。

    递推可以通过矩阵加速一下。由于只有最后M位数才会对下一位产生递推关系,所以我们只要建一个M * M的矩阵加速即可

    #include <map>
    #include <set>
    #include <ctime>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <string>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std;
    inline int read(){int now=0;register char c=getchar();for(;!isdigit(c);c=getchar());
    for(;isdigit(c);now=now*10+c-'0',c=getchar());return now;}
    #define For(i, x, y) for(int i=x;i<=y;i++)  
    #define _For(i, x, y) for(int i=x;i>=y;i--)
    #define Mem(f, x) memset(f,x,sizeof(f))  
    #define Sca(x) scanf("%d", &x)
    #define Sca2(x,y) scanf("%d%d",&x,&y)
    #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define Scl(x) scanf("%lld",&x);  
    #define Pri(x) printf("%d
    ", x)
    #define Prl(x) printf("%lld
    ",x);  
    #define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
    #define LL long long
    #define ULL unsigned long long  
    #define mp make_pair
    #define PII pair<int,int>
    #define PIL pair<int,long long>
    #define PLL pair<long long,long long>
    #define pb push_back
    #define fi first
    #define se second 
    typedef vector<int> VI;
    const double eps = 1e-9;
    const int maxn = 110;
    const int INF = 0x3f3f3f3f;
    int mod = 1e9 + 7; 
    int N,M,K;
    char str[maxn];
    struct Mat{
        LL a[25][25];
        void init(){
            Mem(a,0);
        }
    }base,ans;
    Mat operator * (Mat a,Mat b){
        Mat ans; ans.init();
        for(int i = 0; i < M ; i ++){
            for(int j = 0 ;j < M; j ++){
                for(int k = 0 ; k < M ; k ++){
                    ans.a[i][j] = (ans.a[i][j] + a.a[i][k] * b.a[k][j]) % mod;
                }
            }
        }
        return ans;
    }
    Mat operator ^ (Mat a,int n){
        Mat ans; ans.init();
        for(int i = 0 ; i < M ; i ++) ans.a[i][i] = 1;
        while(n){
            if(n & 1) ans = ans * a;
            a = a * a;
            n >>= 1;
        }
        return ans;
    }
    int nxt[maxn];
    void KMP_Pre(char x[],int m,int *next){
        int i,j;
        j = next[0] = -1;
        i = 0;
        while(i < m){
            while(j != -1 && x[i] != x[j]) j = next[j];
            next[++i] = ++j;
        }
    }
    int main()
    {
        Sca3(N,M,mod); ans.init();
        scanf("%s",str); base.init();
        KMP_Pre(str,strlen(str),nxt);
        for(int i = 0 ; i < M; i ++){
            for(int j = '0' ; j <= '9' ; j ++){
                int k = i;
                while(str[k] != j && k) k = nxt[k];
                if(str[k] == j) k ++;
                base.a[i][k]++;
            }
        }
        LL sum = 0;
        ans.a[0][0] = 1;
        ans = ans * (base ^ N);
        for(int i = 0 ; i < M ; i ++) sum = (sum + ans.a[0][i]) % mod;
        Prl(sum);
        #ifdef VSCode
        system("pause");
        #endif
        return 0;
    }
  • 相关阅读:
    Mybatis(二)入门程序通过id查找用户、模糊查找用户、添加用户、删除用户
    excel测试数据导入
    (转)接口自动化测试之http请求实践总结
    (转)TestNG框架提供两种传入参数的方法:
    Jmeter 集成Excel读写接口参数返回值
    优化问题
    redux
    clientHeight offsetTop scrollTop
    antddesign
    ACMICPC实验室周赛2020.3.6
  • 原文地址:https://www.cnblogs.com/Hugh-Locke/p/9831999.html
Copyright © 2011-2022 走看看