传送门

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

我们为了阅读方便,将数字串称为P串,给定的模式串称为T串。

一开始有这么个暴力想法,就是直接把T串往P串里面匹配,算出有多少种不合法的情况再计算,不过这样并不行,因为在这种算法中有很多种不合法情况被重复计算了。

于是乎看了题解(看题解也看不懂的我)。我们使用dp[i][j]表示在P串中枚举到第i位时,P串有长为j的后缀与T串中长为j的前缀相匹配的情况数。

注意指的是P串枚举位置之前。这样的话,答案就是dp[n][0] + dp[n][1] + …… dp[n][m-1].

也许有疑问,为什么一定要把枚举到P串末尾的情况才算作答案呢?如果在中间随意匹配几个数不可以吗?亦或者,如果中间有不合法情况呢?

我们注意一下转移方式,肯定dp[i][j]是从dp[i-1][j]转移过来的。转移过来的状态肯定是合法的,所以也就保证了枚举到P串第i位时,所有的情况都能保证P串前面没有不合法情况,即完全与T串匹配的情况。所以前面第一种所说的情况被包含,第二种保证不会存在。(具体可以看下面)

既然如此,那我们说说怎么转移,上面说过,枚举到第i位时的情况必然是由枚举到第i-1位时的情况转移过来的。而对于正在被枚举的第i位,可以填入0~9之中任意一个数字,填入之后对于当前匹配的前后缀长度(就是j)有以下三种影响:

1.匹配长度变为0

2.匹配长度在原来的基础上+1

3.匹配长度变为一个在0~原匹配长度之间的数

我们看到这里突然发现,这里和KMP的过程十分相似。KMP就是在逐位枚举的过程中不断确定在这一位字符之前的最长可匹配的前后缀长度,这里也一样。

所以我们只需要先求一遍T串的next数组,之后在DP的时候使用next计算转移方式即可。这里注意一下,虽然分为三种情况,不过实际上写代码的时候直接写一种处理就可以,因为第1,3中情况是失配时候递归调用next的,而第二种情况是匹配上的,直接写在一起就可以啦。

讲了这么多还没说转移方程……通过上面的思路可以知道,转移方程为:dp[i][j] = dp[i-1][0] * a[o][j] + dp[i-1][1] * a[1][j] + …… + dp[i-1][m-1] * a[m-1][j];

其中a[i][j]表示当前匹配长度由i变为j有多少种方法,这个是固定的数目,可以预处理出来。具体的预处理方法就是按照上面的方法,枚举当前匹配长度,从0~m-1,再枚举当前的数是多少(0~9),比如你现在枚举当前匹配长度为i,如果下一位与T串中对应位置匹配,那么a[i][i+1]++,否则令i = next[i],重复上述过程即可。(很像KMP)这样就顺便可以解释为什么没有不合法情况,因为,我们只枚举匹配长度在0~m-1之间的情况,之后的情况我们不枚举,这样自然不会有不合法情况产生。

可能有人会觉得奇怪,比如你从长度为2不可能直接变到长度为5,6……,那么这些情况自然就是0了,还有就是有人会疑问每一位的数字可能不同,怎么方法数是固定的,因为这是你已经枚举的,枚举的时候是会自动考虑所有情况的,可能有点难理解,不过想一想意会一下还是可以的。

DP方程已经好了,不过还没完,n的范围到了10^9,这样O(n)是承受不起的。我们需要使用某些手段加速。重新观察一下DP方程,既然a数组是一个固定的值……

那就可以使用矩阵乘法优化。(因为每一步,dp[i][0~m-1]都是由dp[i-1][0~m-1]通过固定方式转化过来的,想想Fibonacci!)

我们偷一下某位大神的图来说明这件事。

这样就很一目了然了。调用一下矩阵快速幂,直接求a的n次幂,并与一开始构造的单位矩阵相乘即可。(一开始很明显只有f[i][i]是1,其余都是0)

(唉我真是学啥忘啥,这KMP和矩阵乘法都快不会了)

看一下代码。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n')
using namespace std;
const int maxn = ;
int n,mod,len,nxt[maxn],res;
char str[maxn];
struct matrix
{
int f[maxn][maxn];
matrix()
{
memset(f,,sizeof(f));
}
friend matrix operator * (const matrix &a,const matrix &b)
{
matrix c;
rep(i,,len-)
rep(j,,len-)
rep(k,,len-)
c.f[i][j] += a.f[i][k] * b.f[k][j],c.f[i][j] %= mod;
return c;
}
}m,ans; void getnext()
{
int j = ;
nxt[] = ;
rep(i,,len)
{
while(j && str[j+] != str[i]) j = nxt[j];//这种求next是从0开始的,从-1也可以
if(str[j+] == str[i]) j++;
nxt[i] = j;
}
// rep(i,1,len) printf("%d ",nxt[i]);
}
void dp()
{
rep(i,,len-)
rep(j,,)
{
int k;
for(k = i; k; k = nxt[k]) if(str[k+] - '' == j) break;
if(str[k+] - '' == j) k++;
m.f[i][k]++,m.f[i][k] %= mod;
}
return;
}
void pow()
{
rep(i,,len-) ans.f[i][i] = ;
//ans是构造的单位矩阵
while(n)
{
if(n&) ans = ans * m;
m = m * m;
n >>= ;
}
return;
}
int read()
{
int ans = ,op = ;
char ch = getchar();
while(ch < '' || ch > '')
{
if(ch == '-') op = -;
ch = getchar();
}
while(ch >='' && ch <= '')
{
ans *= ;
ans += ch - '';
ch = getchar();
}
return ans * op;
}
int main()
{
n = read(),len = read(),mod = read();
scanf("%s",str+);
getnext(),dp(),pow();
rep(i,,len-) res = (res + ans.f[][i]) % mod;
printf("%d\n",res);
return ;
}
/*
4 3 100
111
*/

HNOI2008 GT考试 (KMP + 矩阵乘法)的更多相关文章

  1. [bzoj1009][HNOI2008]GT考试——KMP+矩阵乘法

    Brief Description 给定一个长度为m的禁止字符串,求出长度为n的字符串的个数,满足: 这个字符串的任何一个字串都不等于给定字符串. 本题是POJ3691的弱化版本. Algorithm ...

  2. BZOJ 1009 [HNOI2008]GT考试 (KMP+矩阵乘法)

    ---恢复内容开始--- 题目大意:给定一个由数字构成的字符串A(len<=20),让你选择一个长度为n(n是给定的)字符串X,一个合法的字符串X被定义为,字符串X中不存在任何一段子串与A完全相 ...

  3. BZOJ1009: [HNOI2008]GT考试(KMP+矩阵乘法)

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

  4. BZOJ_1009_[HNOI2008]GT考试_KMP+矩阵乘法

    BZOJ_1009_[HNOI2008]GT考试_KMP+矩阵乘法 Description 阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考 ...

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

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

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

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

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

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

  8. 题解:BZOJ 1009 HNOI2008 GT考试 KMP + 矩阵

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

  9. bzoj 1009 [HNOI2008]GT考试——kmp+矩阵优化dp

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1009 首先想到 确保模式串不出现 就是 确保每个位置的后缀不是该模式串. 为了dp,需要记录 ...

  10. bzoj1009 [HNOI2008]GT考试——KMP+矩阵快速幂优化DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1009 字符串计数DP问题啊...连题解都看了好多好久才明白,别提自己想出来的蒟蒻我... 首 ...

随机推荐

  1. easyui分页时,总页数出错

    错误出现 MyBatis用easyui写后台分页代码时,出现翻页后显示总页数错误 代码如下 可能原因在于后台mappers.xml里的sql语句错误 <select id="getPr ...

  2. centos 安装php缓存 apc或zend-opcode

    去官方下载apc:pecl.php.net 搜索apc,安装最新的. #wget http://pecl.php.net/get/APC# tar -xzvf APC-3.1.9.tgz#cd  AP ...

  3. 【paddle学习】词向量

    http://spaces.ac.cn/archives/4122/   关于词向量讲的很好 上边的形式表明,这是一个以2x6的one hot矩阵的为输入.中间层节点数为3的全连接神经网络层,但你看右 ...

  4. [CSS3] Understand CSS Selector Specificity

    It is hard to explain css selector specificty, to easy way to understand it is by playing around wit ...

  5. HDU 1028 Ignatius and the Princess III (母函数或者dp,找规律,)

    Ignatius and the Princess III Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K ...

  6. [LeetCode] 038. Count and Say (Easy) (C++/Python)

    索引:[LeetCode] Leetcode 题解索引 (C++/Java/Python/Sql) Github: https://github.com/illuz/leetcode 038. Cou ...

  7. sed 修连接文件,有坑

    -bash-4.1# ll /etc/rc.local  lrwxrwxrwx. 1 root root 13 Aug 15  2014 /etc/rc.local -> rc.d/rc.loc ...

  8. Ubuntu 16.04 LTS安装Eclipse配置Pydev

    原材料: 下载 jdk-8u121-linux-x64.tar.gz 下载 eclipse-jee-neon-2-linux-gtk-x86_64.tar.gz 1.安装jdk sudo mkdir ...

  9. 基于redis集群实现的分布式锁,可用于秒杀商品的库存数量管理,有測试代码(何志雄)

    转载请标明出处. 在分布式系统中,常常会出现须要竞争同一资源的情况,本代码基于redis3.0.1+jedis2.7.1实现了分布式锁. redis集群的搭建,请见我的另外一篇文章:<>& ...

  10. What is the difference between message queue pattern and publish-subscribe?

    What is the difference between message queue pattern and publish-subscribe? - Quora https://www.quor ...