bzoj 1009 [HNOI2008]GT考试(DP+KMP+矩阵乘法)
【题目链接】
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+矩阵乘法)的更多相关文章
- BZOJ 1009: [HNOI2008]GT考试( dp + 矩阵快速幂 + kmp )
写了一个早上...就因为把长度为m的也算进去了... dp(i, j)表示准考证号前i个字符匹配了不吉利数字前j个的方案数. kmp预处理, 然后对于j进行枚举, 对数字0~9也枚举算出f(i, j) ...
- bzoj1009: [HNOI2008]GT考试(kmp+矩阵乘法)
1009: [HNOI2008]GT考试 题目:传送门 题解: 看这第一眼是不是瞬间想起组合数学??? 没错...这样想你就GG了! 其实这是一道稍有隐藏的矩阵乘法,好题! 首先我们可以简化一下题意: ...
- bzoj 1009: [HNOI2008]GT考试【kmp+dp+矩阵快速幂】
看n和k的范围长得就很像矩阵乘法了 设f[i][j]表示到第i个位置的后缀最长匹配目标串的j位.转移的话显然是枚举0~9,然后选择f[i+1]中能被他转移的加起来,需要用到next数组.然后构造矩阵的 ...
- P3193 [HNOI2008]GT考试(KMP+矩阵乘法加速dp)
P3193 [HNOI2008]GT考试 思路: 设\(dp(i,j)\)为\(N\)位数从高到低第\(i\)位时,不吉利数字在第\(j\)位时的情况总数,那么转移方程就为: \[dp(i,j)=dp ...
- HNOI2008 GT考试 (KMP + 矩阵乘法)
传送门 这道题目的题意描述,通俗一点说就是这样:有一个长度为n的数字串(其中每一位都可以是0到9之间任意一个数字),给定一个长度为m的模式串,求有多少种情况,使得此模式串不为数字串的任意一个子串.结果 ...
- BZOJ 1009: [HNOI2008]GT考试(kmp+dp+矩阵优化)
http://www.lydsy.com/JudgeOnline/problem.php?id=1009 题意: 思路:真的是好题啊! 对于这种题目,很有可能就是dp,$f[i][j]$表示分析到第 ...
- BZOJ 1009 [HNOI2008]GT考试 (KMP + 矩阵快速幂)
1009: [HNOI2008]GT考试 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 4266 Solved: 2616[Submit][Statu ...
- bzoj 1009: [HNOI2008]GT考试 -- KMP+矩阵
1009: [HNOI2008]GT考试 Time Limit: 1 Sec Memory Limit: 162 MB Description 阿申准备报名参加GT考试,准考证号为N位数X1X2.. ...
- bzoj 1009:[HNOI2008]GT考试
这道题机房n多人好久之前就A了…… 我到现在才做出来…… 一看就是DP+矩阵乘法,但是一开始递推式推错了…… 正确的递推式应该是二维的…… f[i][j] 表示第准考证到第 i 位匹配了 j 位的方案 ...
随机推荐
- android MD5
public static String MD5(String str) { MessageDigest md5 = null; try { md5 = MessageDigest.getInstan ...
- 使用phantomjs实现highcharts等报表通过邮件发送
使用phantomjs实现highcharts等报表通过邮件发送(本文仅提供完整解决方案和实现思路,完全照搬不去整理代码无法马上得到效果) 前不久项目组需要将测试相关的质量数据通过每日自动生成报表 ...
- 特殊的css样式
在一定范围大小变化的div .div { width:auto; height:auto; min-height:100px; min-width:100px; max-height:200px; m ...
- cdev_init函数
linux-2.6.22/include/linux/cdev.hstruct cdev { struct kobject kobj; // 每个 cdev 都是一个 kobje ...
- hadoop2 环境的搭建(自动HA)
zookeeper:hadoop112.hadoop113.hadoop114 namenode:hadoop110和hadoop111 datanode:hadoop112.hadoop113.ha ...
- NDK(16)Jni中GetStaticFieldID和GetMethodID 中的类型标识串
env在GetStaticFieldID和GetMethodID 时,函数参数和返回值的类型要指定类型标识串,如: jmethodID init = env->GetMethodID(clz,& ...
- git push default
今天使用git push的时候出现了如下提示: warning: push.default is unset; its implicit value is changing in Git 2.0 fr ...
- Internet Explorer for Mac the Easy Way: Run IE 7, IE8, & IE9 Free in a Virtual Machine
From link: http://osxdaily.com/2011/09/04/internet-explorer-for-mac-ie7-ie8-ie-9-free/ If you’re ...
- bzoj2432
被虐的体无完肤, 直接给题解地址吧:http://vfleaking.blog.163.com/blog/static/174807634201341721051604/ ; ..,..] of in ...
- uva12169 Disgruntled Judge
扩展欧几里得. 枚举a,根据x1,x3和递推式可得. (a+1)*b-k*mod=f[3]-a*a*b. 通过扩展欧几里得求出b. 带入原式进行计算. #include<cstdio> # ...