zoukankan      html  css  js  c++  java
  • 洛谷P3193 [HNOI2008]GT考试(KMP,矩阵)

    传送门

    大佬讲的真吼->这里

    首先考虑dp,设$f[i][j]$表示长串匹配到第$i$位,短串最多匹配到$j$位时的方案数

    那么答案就是$sum_{i=0}^{m-1}f[n][i]$

    然后考虑一下dp的转移,一种是加进的新字符$i+1$与$j+1$匹配,那么$dp[i][j]$可以直接转移到$dp[i+1][j+1]$

    然后如果不匹配怎么办?这种时候,有可能新串的一个后缀和短串的一个前缀有了匹配

    对于这一点,我们就是要知道,对于一个匹配到长度为$j$的串,转移到$k$的串的方案,也就对于长度为$i$的串,加一个数字,能加入多少种数字,使得长度为$j$的匹配变成长度为$k$的匹配

    然后这个可以用kmp计算

    然后看一下dp式子$f[i][j]=sum{k=0}^{m-1}f[i-1][k]*g[k][j]$

    那这就是一个矩阵乘法了……因为$g[i][j]$是固定不变的,所以把$f[i][j]$看做一个矩阵

    那么$F[i]=F[i-1]*G$

    那么矩阵快速幂一下就行了

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 using namespace std;
     6 const int N=10005;
     7 int f[N][30],n,m,mod;
     8 int kmp[N],match[N][55];char s[N];
     9 inline void init(){
    10     kmp[0]=-1;
    11     for(int i=1;i<=m;++i){
    12         int j=kmp[i-1];
    13         while((~j)&&s[j+1]!=s[i]) j=kmp[j];
    14         kmp[i]=j+1;
    15     }
    16     kmp[0]=0;
    17     for(int i=0;i<m;++i)
    18     for(int j='0';j<='9';++j){
    19         int tmp=i;
    20         while(s[tmp+1]!=j&&tmp) tmp=kmp[tmp];
    21         if(s[tmp+1]==j) ++tmp;
    22         if(tmp<m) ++match[i][tmp];
    23     }
    24 }
    25 struct Matrix{
    26     int g[25][25];
    27     Matrix(){memset(g,0,sizeof(g));}
    28     Matrix operator *(Matrix B){
    29         Matrix res;
    30         for(int i=0;i<m;++i)
    31         for(int j=0;j<m;++j)
    32         for(int k=0;k<m;++k)
    33         (res.g[i][j]+=g[i][k]*B.g[k][j])%=mod;
    34         return res;
    35     }
    36 }F,G;
    37 inline Matrix ksm(Matrix A,int k){
    38     Matrix res;
    39     for(int i=0;i<=m;++i) res.g[i][i]=1;
    40     while(k){
    41         if(k&1) res=res*A;
    42         A=A*A,k>>=1;
    43     }
    44     return res;
    45 }
    46 int main(){
    47 //    freopen("testdata.in","r",stdin);
    48     scanf("%d%d%d%s",&n,&m,&mod,s+1);
    49     init();
    50     F.g[0][0]=1;
    51     for(int i=0;i<=m;++i)
    52     for(int j=0;j<=m;++j)
    53     G.g[i][j]=match[i][j];
    54     G=ksm(G,n);
    55     F=F*G;
    56     int ans=0;
    57     for(int i=0;i<m;++i) (ans+=F.g[0][i])%=mod;
    58     printf("%d
    ",ans);
    59     return 0;
    60 }
  • 相关阅读:
    基本技能训练之线程
    关于UEditor的使用配置(图片上传配置)
    PAT 乙级练习题1002. 写出这个数 (20)
    codeforces 682C Alyona and the Tree DFS
    codeforces 681D Gifts by the List dfs+构造
    codeforces 678E Another Sith Tournament 概率dp
    codeforces 680E Bear and Square Grid 巧妙暴力
    codeforces 678D Iterated Linear Function 矩阵快速幂
    codeforces 679A Bear and Prime 100 交互
    XTUOJ 1248 TC or CF 搜索
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9640595.html
Copyright © 2011-2022 走看看