【题目链接】

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

【题意】

给定一个字符串T,问长度为n且不包含串T的字符串有多少种。

【思路】

设长度为i的串与T匹配长度为j,有转移式如下:

f[i+1][j+1]+=f[i][j]

f[i+1][k]+=f[i][j]

第一种是匹配成功,第二种是匹配失败。注意如果匹配失败匹配长度并不一定变为0,考虑如果匹配失败f[i][j]可以转移到哪,假设新字符为c,则可以用KMP算法预处理出fail数组,从而计算出应该转移到的位置pos。

考虑到n比较大,而f的计算又是有规律的,我们采用矩阵乘法优化DP。

如果i可以转移到pos,则在转移矩阵A中使A[i][pos]++,代表f[cur][pos]的计算需要累加一次f[cur-1][i]。

注意程序中的fail[i]代表的是i刚好与fail[i]匹配。

【代码】

 #include<cstdio>
#include<cstring>
#include<iostream>
#define FOR(a,b,c) for(int a=b;a<=c;a++)
using namespace std; typedef long long ll;
const int maxn = ; char s[maxn];
int f[maxn],MOD,n,m,K; struct Matrix {
int r,c;
ll N[maxn][maxn];
void init(int r,int c) {
this->r=r,this->c=c;
memset(N,,sizeof(N));
}
Matrix operator * (const Matrix B) const {
Matrix C; C.init(r,B.c);
for(int i=;i<r;i++)
for(int j=;j<B.c;j++)
for(int k=;k<c;k++)
C.N[i][j]=(C.N[i][j]+(ll)N[i][k]*B.N[k][j])%MOD;
return C;
}
Matrix Pow(int p) {
Matrix tmp=*this,ans;
ans.init(r,r);
for(int i=;i<r;i++) ans.N[i][i]=;
while(p) {
if(p&) ans=ans*tmp;
tmp=tmp*tmp; p>>=;
}
return ans;
}
}A; void get_fail() //所构造fail 意为i与f[i]处匹配
{
int j=;
for(int i=;i<m;i++) {
while(j&&s[j+]!=s[i]) j=f[j];
if(s[j+]==s[i]) j++;
f[i]=j;
}
} int main()
{
scanf("%d%d%d%s",&n,&m,&MOD,s+);
get_fail();
A.init(m+,m+);
FOR(i,,m-)
FOR(j,,) {
int x=i;
while(x&&s[x+]-''!=j) x=f[x];
if(j==s[x+]-'') A.N[i][x+]++;
else A.N[i][]++;
}
A=A.Pow(n);
ll ans=;
FOR(i,,m-) ans=(ans+A.N[][i])%MOD;
printf("%lld\n",ans);
return ;
}

bzoj 1009 [HNOI2008]GT考试(DP+KMP+矩阵乘法)的更多相关文章

  1. BZOJ 1009: [HNOI2008]GT考试( dp + 矩阵快速幂 + kmp )

    写了一个早上...就因为把长度为m的也算进去了... dp(i, j)表示准考证号前i个字符匹配了不吉利数字前j个的方案数. kmp预处理, 然后对于j进行枚举, 对数字0~9也枚举算出f(i, j) ...

  2. bzoj1009: [HNOI2008]GT考试(kmp+矩阵乘法)

    1009: [HNOI2008]GT考试 题目:传送门 题解: 看这第一眼是不是瞬间想起组合数学??? 没错...这样想你就GG了! 其实这是一道稍有隐藏的矩阵乘法,好题! 首先我们可以简化一下题意: ...

  3. bzoj 1009: [HNOI2008]GT考试【kmp+dp+矩阵快速幂】

    看n和k的范围长得就很像矩阵乘法了 设f[i][j]表示到第i个位置的后缀最长匹配目标串的j位.转移的话显然是枚举0~9,然后选择f[i+1]中能被他转移的加起来,需要用到next数组.然后构造矩阵的 ...

  4. P3193 [HNOI2008]GT考试(KMP+矩阵乘法加速dp)

    P3193 [HNOI2008]GT考试 思路: 设\(dp(i,j)\)为\(N\)位数从高到低第\(i\)位时,不吉利数字在第\(j\)位时的情况总数,那么转移方程就为: \[dp(i,j)=dp ...

  5. HNOI2008 GT考试 (KMP + 矩阵乘法)

    传送门 这道题目的题意描述,通俗一点说就是这样:有一个长度为n的数字串(其中每一位都可以是0到9之间任意一个数字),给定一个长度为m的模式串,求有多少种情况,使得此模式串不为数字串的任意一个子串.结果 ...

  6. BZOJ 1009: [HNOI2008]GT考试(kmp+dp+矩阵优化)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1009 题意: 思路:真的是好题啊! 对于这种题目,很有可能就是dp,$f[i][j]$表示分析到第 ...

  7. BZOJ 1009 [HNOI2008]GT考试 (KMP + 矩阵快速幂)

    1009: [HNOI2008]GT考试 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 4266  Solved: 2616[Submit][Statu ...

  8. bzoj 1009: [HNOI2008]GT考试 -- KMP+矩阵

    1009: [HNOI2008]GT考试 Time Limit: 1 Sec  Memory Limit: 162 MB Description 阿申准备报名参加GT考试,准考证号为N位数X1X2.. ...

  9. bzoj 1009:[HNOI2008]GT考试

    这道题机房n多人好久之前就A了…… 我到现在才做出来…… 一看就是DP+矩阵乘法,但是一开始递推式推错了…… 正确的递推式应该是二维的…… f[i][j] 表示第准考证到第 i 位匹配了 j 位的方案 ...

随机推荐

  1. mysql字段的适当冗余有利于提高查询速度

    CREATE TABLE `comment` (  `c_id` int(11) NOT NULL auto_increment COMMENT '评论ID',  `u_id` int(11) NOT ...

  2. 企业用户2T(含秒传),普通用户20G

    周鸿祎一定要看的建议(要求置顶):可以解决本次云盘事件的建议!!! 2016-10-23 20:23 | 复制链接 | 淘帖 461334 本帖最后由 cqthxin 于 2016-10-23 20: ...

  3. 本人arcgis api for javascript中常见错误总结

    1. 2.对象不支持"replace"属性或方法 解决办法:一般在ie中执行js会报这样的错误,基本问题就是你引用了某个对象中不存在的方法,可能是这个方法本来存在而你写错了,或者调 ...

  4. Android ListView高度自适应和ScrollView冲突解决

    在ScrollView中嵌套使用ListView,ListView只会显示一行到两行的数据.起初我以为是样式的问题,一直在对XML文件的样式进行尝试性设置,但始终得不到想要的效果.后来在网上查了查,S ...

  5. 机器学习 —— 概率图模型(推理:MAP)

    MAP 是最大后验概率的缩写.后验概率指的是当有一定观测结果的情况下,对其他随机变量进行推理.假设随机变量的集合为X ,观察到的变量为 e, W = X-e , AP = P(W|e). 后验概率和联 ...

  6. 【原创】30分钟入门 github

    很久没更新了,这篇文章重点在github的入门使用,读者可以下载github for windows shell,边看边操作,加深印象. 好了,30分钟的愉快之旅开始吧: 一.github使用的注意事 ...

  7. inand和emmc区别

    简单来说:inand式sandisk公司做的一款符合emmc标准的一个emmc存储器! ----

  8. Null-conditional Operators

    https://msdn.microsoft.com/en-us/library/dn986595.aspx x?.y – null conditional member access. Return ...

  9. C++ STL之set的基本操作

    set是集合,虽然也存在键值和实值,不过两者根本就是同一个值,键值的设置完全就是为了满足红黑树的底层结构,set操作与map很像不过也有些不同. 1. set迭代器与map的不同: (1)set使用接 ...

  10. java_十进制数转换为二进制,八进制,十六进制数的算法

    java_十进制数转换为二进制,八进制,十六进制数的算法 java Ê®½øÖÆÊýת»»Îª¶þ½øÖÆ,°Ë½øÖÆ,Ê®Áù½øÖÆÊýµÄË㕨 using System; using S ...