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

字符串计数DP问题啊...连题解都看了好多好久才明白,别提自己想出来的蒟蒻我...

首先要设计一个不太好想的状态:f[i][j]表示大串上到第 i 位时有小串前 j 位的后缀,且不包含整个小串的方案数;

也就是如果小串是 12312 , f[5][3] 表示目前大串的情况是 **123... ;

这个状态要从 i 转移到 i+1 ,还需要一个帮助它的数组 a,a[i][j]表示在长度为 i 的后缀后面加一个数字能变成长度为 j 的后缀的方案数;

也就是说,对于 12312,从0到4的 a 数组应该如下:

9 1 0 0 0

8 1 1 0 0

8 1 0 1 0

9 0 0 0 1

8 1 0 0 0

a 数组的定义可以联想到 kmp 算法,事实上它就是通过 kmp 算法的 nxt 数组求得;

于是就可以得到转移方程:f[i][j] = ∑(0<=k<m) f[i-1][k] * a[k][j]

然后发现对于每一步,进行的转移都是相同的;

所以可以用矩阵快速幂来优化,转移矩阵就是 a 数组;

看了好多好多博客才明白...

这篇博客写得很好:https://blog.csdn.net/loi_dqs/article/details/50897662

尤其是代码真的简洁!所以模仿着写了。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
int n,m,mod,nxt[],sum;
char s[];
struct Matrix{
int n,m,a[][];
Matrix(int x=,int y=):n(x),m(y) {memset(a,,sizeof a);}
void init()
{
for(int i=;i<n;i++)a[i][i]=;//0 ~ n-1
}
Matrix operator * (const Matrix &y) const
{
Matrix x(n,y.m);
for(int i=;i<n;i++)//从0到n-1
for(int k=;k<m;k++)
for(int j=;j<y.m;j++)
(x.a[i][j]+=(ll)a[i][k]*y.a[k][j]%mod)%=mod;
return x;
}
};
void getnxt()
{
nxt[]=nxt[]=;//第0位有字符,但含义是无匹配
for(int i=;i<m;i++)
{
// int k=i;
int k=nxt[i];
while(s[i]!=s[k]&&k)k=nxt[k];
nxt[i+]=(s[i]==s[k])?k+:;//前一位的nxt冒进一位,对应下面从0开始的字符串匹配
}
}
Matrix pw(Matrix x,int k)
{
Matrix ret(x.n,x.m); ret.init();
for(;k;k>>=,x=x*x)
if(k&)ret=ret*x;
return ret;
}
int main()
{
scanf("%d%d%d%s",&n,&m,&mod,&s);
getnxt();
Matrix f(m,m);
for(int i=;i<m;i++)
for(int j='';j<='';j++)//第i位上填j
{
int k=i;//已经有长度为i的前缀,而k对应字符串上i的后一位
while(k&&s[k]!=j)k=nxt[k];//冒进一位的nxt,表示给i后一位进行匹配
if(s[k]==j)k++;//匹配到了第k位,也就是有了k+1长度的前缀
if(k!=m)f.a[i][k]++;
}
Matrix fn=pw(f,n);
Matrix ans(,m);
ans.a[][]=; ans=ans*fn;
for(int i=;i<m;i++)
(sum+=ans.a[][i])%=mod;
printf("%d",sum);
return ;
}

bzoj1009 [HNOI2008]GT考试——KMP+矩阵快速幂优化DP的更多相关文章

  1. [bzoj1009](HNOI2008)GT考试 (kmp+矩阵快速幂加速递推)

    Description 阿 申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字.他的不吉利数学 A1A2...Am(0&l ...

  2. 【bzoj1009】[HNOI2008]GT考试(矩阵快速幂优化dp+kmp)

    题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1009 这道题一看数据范围:$ n<=10^9 $,显然不是数学题就是矩乘快速幂优 ...

  3. 2018.10.22 bzoj1009: [HNOI2008]GT考试(kmp+矩阵快速幂优化dp)

    传送门 f[i][j]f[i][j]f[i][j]表示从状态"匹配了前i位"转移到"匹配了前j位"的方案数. 这个东西单次是可以通过跳kmp的fail数组得到的 ...

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

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

  5. 2018.10.23 bzoj1297: [SCOI2009]迷路(矩阵快速幂优化dp)

    传送门 矩阵快速幂优化dp简单题. 考虑状态转移方程: f[time][u]=∑f[time−1][v]f[time][u]=\sum f[time-1][v]f[time][u]=∑f[time−1 ...

  6. 2018.10.16 uoj#340. 【清华集训2017】小 Y 和恐怖的奴隶主(矩阵快速幂优化dp)

    传送门 一道不错的矩阵快速幂优化dpdpdp. 设f[i][j][k][l]f[i][j][k][l]f[i][j][k][l]表示前iii轮第iii轮还有jjj个一滴血的,kkk个两滴血的,lll个 ...

  7. 省选模拟赛 Problem 3. count (矩阵快速幂优化DP)

    Discription DarrellDarrellDarrell 在思考一道计算题. 给你一个尺寸为 1×N1 × N1×N 的长条,你可以在上面切很多刀,要求竖直地切并且且完后每块的长度都是整数. ...

  8. [HNOI2008][bzoj1009] GT考试 [KMP+矩阵快速幂]

    题面 传送门 思路 首先,如果$n$和$m$没有那么大的话,有一个非常显然的dp做法: 设$dp[i][j]$表示长度为i的字符串,最后j个可以匹配模板串前j位的情况数 那么显然,答案就是$\sum_ ...

  9. BZOJ 1009 [HNOI2008]GT考试(矩阵快速幂优化DP+KMP)

    题意: 求长度为n的不含长为m的指定子串的字符串的个数 1s, n<=1e9, m<=50 思路: 长见识了.. 设那个指定子串为s f[i][j]表示长度为i的字符串(其中后j个字符与s ...

随机推荐

  1. 【原】thinkphp实现存储session至redis

    Thinkphp\Library\Think\Session\Driver中新建redis缓存文件:Redis.class.php Thinkphp\Common\function.php 中 fun ...

  2. react 返回上一页

    import * as React from 'react' import { Layout } from 'antd'; import creatHistory from 'history/crea ...

  3. UVA - 12325 Zombie's Treasure Chest (分类搜索)

    题目: 有一个体积为N的箱子和两种数量无限的宝物.宝物1的体积为S1,价值为V1:宝物2的体积为S2,价值为V2.输入均为32位带符号整数.计算最多能装多大价值的宝物,每种宝物都必须拿非负整数个. 思 ...

  4. <SpringMvc>入门七 拦截器

    什么是拦截器 1.SpringMVC框架中的拦截器用于 对处理器 进行预处理和后处理的技术. 2.可以定义拦截器链,按照顺序执行. 3.拦截器和过滤器功能类似,区别在 拦截器 过滤器 过滤器是Serv ...

  5. 制作一个最小Linux系统

    使用的是itop4412开发板(仅记录个人的学习回顾,如有不当之处欢迎指出) ---------致谢 准备:busybox软件.uboot(一般和开发板配套).zImage(kernel内核).ram ...

  6. 第十二节:Web爬虫之MongoDB数据库安装与数据存储

    MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功 ...

  7. BZOJ 4094 USACO 2013 Dec. Optimal Milking

    线段树 每个节点保存4个值,both表示左右端点都取,neither表示左右端点都不取,left表示只取左端点,right表示只取右端点. 维护的特殊姿势: $cur$的$both=max(ls.l+ ...

  8. 2014年武汉的IT行情好像不太好(续):20个月过后,再看当时面试过的几个公司--武汉财富基石-崩盘,辣妈萌宝-创业失败,朋友公司转交他人管理

     2014年9月的时候,写过一篇面试的总结性质的文章,"2014年武汉的IT行情好像不太好". 原文地址:blog.csdn.net/fansunion/article/detai ...

  9. 关于jupyter notebook

    直接点击进行跳转阅读:https://zhuanlan.zhihu.com/p/33105153

  10. [luoguP1403] [AHOI2005]约数研究(这。。。)

    传送门 用类似筛法的原理,就好啦 ——代码 #include <cstdio> int n, ans; int a[1000001]; int main() { int i, j; sca ...