Luogu P10581 蓝桥杯2024国A 重复的串 题解 [ 蓝 ] [ KMP ] [ 动态规划 ] [ 矩阵加速 ]
重复的串:KMP + dp 的板子题。
暴力 dp
设计 \(dp_{k,i,j}\) 表示主串匹配到第 \(i\) 位,模式串有 \(j\) 位已匹配完成,目前已完成 \(k\) 次匹配的方案数。
不难写出暴力的填表法转移式子,发现是平方级别的转移,所以使用填表法不行,我们尝试刷表法。
\(dp_{k,i,j}\) 要转移去的地方显然是第 \(i+1\) 位,于是我们要观察 \(j\) 里哪些是合法的,很容易就想到用 KMP 加速这个过程,因为 KMP 做的也是匹配到某一位后,求出下一位的最大匹配长度。
假设 \(m\) 为模式串的长度。
对于 \(dp_{k,i,j}\) 我们枚举第 \(i+1\) 位的字符是什么,依次和当前需要匹配的字符进行比较,然后用 KMP 的 next 数组求出下一位的最大匹配长度 \(l\):
- 当最大匹配长度为 \(m\) 时,这时候 \(k\) 就要 \(+1\),所以 \(dp_{k+1,i+1,next_l} \gets dp_{k+1,i+1,next_l}+dp_{k,i,j}\)。
- 当最大匹配长度小于 \(m\) 时,直接转移即可,\(dp_{k,i+1,l} \gets dp_{k,i+1,l}+dp_{k,i,j}\)。
时间复杂度是 \(O(k|\sum|n)\) 的,显然不可过。
矩阵优化
发现当值域非常大的 \(i\) 确定时,剩下两维的数量很小,只有 \(90\) 个值左右,考虑矩阵优化 dp。
我们把 \(i\) 这一位提取到前面来,作为快速幂的幂次即可。
构造矩阵有点难描述,看代码吧,大体就是做一遍上面的那个转移,注意细节问题就好了。
另外,当 \(j=m\) 时,不能进行转移。
时间复杂度 \(O((k|\sum|)^3 \log n)\)。
关于完整匹配
本题中,完整匹配后可以跳到 \(next\) 处,是因为这样统计方案不会重复。而其他题中,有时候完整匹配是不能直接跳回 \(next\) 的,因为完全匹配后和 \(next\) 的情况可能是不同的。这时候就要对 \(next\) 进行转移,其实就不用特判 \(next\) 就行了,下次它会自己跳回去自己的 \(next\) 的。
代码
#include <bits/stdc++.h>
#define fi first
#define se second
#define lc (p<<1)
#define rc ((p<<1)|1)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pi;
const ll mod=998244353;
int n,ne[35],m;
char c[35];
struct mat{
ll a[105][105];
mat(){memset(a,0,sizeof(a));}
mat operator*(const mat &t)const{
mat res;
for(int i=0;i<=100;i++)
{
for(int k=0;k<=100;k++)
{
for(int j=0;j<=100;j++)
{
res.a[i][j]=(res.a[i][j]+a[i][k]*t.a[k][j])%mod;
}
}
}
return res;
}
};
void construct_dp(mat &dp)
{
for(int lv=0;lv<=2;lv++)
{
int ns=1+lv*(m+1);
for(int i=ns;i<ns+m;i++)
{
for(int j=0;j<26;j++)
{
char nc=('a'+j);
int now=i-ns;
while(now&&nc!=c[now+1])now=ne[now];
if(nc==c[now+1])now++;
if(now==m)
{
if(lv==2)continue;
now=ne[now];
dp.a[i][ns+m+1+now]=(dp.a[i][ns+m+1+now]+1)%mod;
}
else dp.a[i][ns+now]=(dp.a[i][ns+now]+1)%mod;
}
}
}
}
void construct_init(mat &s){s.a[1][1]=1;}
mat qpow(mat a,ll b)
{
mat res;
for(int i=0;i<=100;i++)res.a[i][i]=1;
while(b)
{
if(b&1)res=res*a;
a=a*a;
b>>=1;
}
return res;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>c+1>>n;
m=strlen(c+1);
int now=0;
for(int i=2;i<=m;i++)
{
while(now&&c[now+1]!=c[i])now=ne[now];
if(c[now+1]==c[i])now++;
ne[i]=now;
}
mat dp;
construct_dp(dp);
mat s;
construct_init(s);
dp=s*qpow(dp,n);
ll ans=0;
for(int i=1+2*(m+1);i<1+3*(m+1);i++)ans=(ans+dp.a[1][i])%mod;
cout<<ans;
return 0;
}
Luogu P10581 蓝桥杯2024国A 重复的串 题解 [ 蓝 ] [ KMP ] [ 动态规划 ] [ 矩阵加速 ]的更多相关文章
- 平方十位数(蓝桥杯第八届国赛真题 JAVA-B组)
思路:从大到小枚举,判断其平方是否不重复 答案:9814072356 //水题 标题:平方十位数 由0~9这10个数字不重复.不遗漏,可以组成很多10位数字. 这其中也有很多恰好是平方数(是某个数的平 ...
- P8701 [蓝桥杯 2019 国 B] 第八大奇迹
简要题意 你需要维护一个长度为 \(L\) 的序列 \(a\),初始时全部都是 \(0\),有 \(N\) 个操作,支持: C p x,将 \(a_p\) 修改为 \(x\). Q a b,输出 \( ...
- P8622 [蓝桥杯 2014 国 B] 生物芯片
简要题意 有 \(N\) 个二进制数,编号为 \(1\sim N\),初始时都是 \(0\).博士进行了 \(N-1\) 次操作,在第 \(i\) 次操作时,会将 \(1\sim N\) 中所有编号为 ...
- P8618 [蓝桥杯 2014 国 B] Log 大侠
简要题意 给你一个长度为 \(n\) 的正整数序列 \(a\),有 \(m\) 个询问,每一个询问给出一个区间 \([l,r]\).定义函数 \(f(x)=\lfloor\log_{2}(x)+1\r ...
- P8796 [蓝桥杯 2022 国 AC] 替换字符
题面 给定一个仅含小写英文字母的字符串 \(s\) 和 \(m\) 次操作,每次操作选择一个区间 \([l_i,r_i]\) 将 \(s\) 的该区间中的所有字母 \(x_i\) 全部替换成字母 \( ...
- 算法笔记_106:蓝桥杯练习 算法提高 周期字串(Java)
目录 1 问题描述 2 解决方案 2.1 第一印象解法(80分) 2.2 借鉴网友解法(100分) 1 问题描述 问题描述 右右喜欢听故事,但是右右的妈妈总是讲一些“从前有座山,山里有座庙,庙里有 ...
- [蓝桥杯]ALGO-87.算法训练_字串统计
问题描述 给定一个长度为n的字符串S,还有一个数字L,统计长度大于等于L的出现次数最多的子串(不同的出现可以相交),如果有多个,输出最长的,如果仍然有多个,输出第一次出现最早的. 输入格式 第一行一个 ...
- 2019年第十届蓝桥杯c++A组java/c++组题解
#include<iostream> #include<vector> using namespace std; vector <int > vec; long l ...
- 2018年蓝桥杯B组C/C++决赛题目
自己的博客排版,自我感觉略好一点. 先放上题目. 点击查看2018年蓝桥杯B组C/C++决赛题目题解 1.换零钞 x星球的钞票的面额只有:100元,5元,2元,1元,共4种. 小明去x星旅游, ...
- 2019年第十届蓝桥杯国赛总结(JavaA组)
JavaA组国二,可以报销了~ JA死亡之组可不是盖的,rank12的排名还是拿不到国一啊(只有五个.. 出成绩的一刻波澜不惊,毕竟去年有国一了不慌哈哈哈 不过对我来说这个结果还算意料之外吧,毕竟大三 ...
随机推荐
- Vue.js 插件
1.前言 vue的插件其实通过操作Vue这个对象,为其扩展新的功能.例如: // 1. 添加全局方法或 property Vue.myGlobalMethod = function () { // 逻 ...
- PLC编程—数据类型
CPU 型号不同,实际的有效数据类型与文中略有不同(大同小异) 数据类型概述 基本数据类型(二进制数.整数.浮点数.定时器.DATE.TOD.LTOD.CHAR.WCHAR) 复杂数据类型(DT.LD ...
- HarmonyOS鸿蒙开发 - 解决上下两栏白边 - 沉浸式效果
鸿蒙应用开发从入门到入行 预览器上下两栏白边 自从HarmonyOS升级到release版后,很多同学会问猫林老师:为什么他的预览器上下有白边,为什么明明根容器写了宽高百分百但没铺满.如下图 白边原因 ...
- 硬件开发笔记(三十二):TPS54331电源设计(五):原理图BOM表导出、元器件封装核对
前言 一个12V转5V.3.3V和4V的电源电路设计好了,下一步导出BOM表,二次核对元器件型号封装,这是可以生产前的最后一步了. 导出BOM表 步骤一:打开原理图 打开项目,双击点开原理 ...
- Qt/C++音视频开发62-电子放大/按下选择区域放大显示/任意选取区域放大
一.前言 电子放大这个功能思考了很久,也是一直拖到近期才静下心来完整这个小功能,这个功能的前提,主要得益于之前把滤镜打通了,玩出花样来了,只要传入对应的滤镜字符串,就可以实现各种各样的效果,然后查阅滤 ...
- Qt音视频开发30-qmedia内核qt4方案phonon播放(支持视频流)
一.前言 在Qt4中如果需要播放视频,一般用phonon多媒体框架,这应该就是Qt5/Qt6中多媒体框架的前身(查阅qmultimedia模块的相关代码可以发现架构几乎雷同,除了部分命名变了以外),p ...
- 关于Qt数据库开发的一些冷知识
一.知识要点 Qt即支持库的形式直接和数据库通信,也支持ODBC数据源的形式和各种数据库通信,这样就涵盖了所有的情况. Qt数据库程序打包发布,所有前提:注意区分32/64位,你的程序是32位的就必须 ...
- Redis源码历史版本下载地址和Redis的Windows版本服务端/客户端下载地址
Redis源码历史版本下载地址:http://download.redis.io/releases/ Redis的Windows版本服务端/客户端下载地址:https://github.com/mic ...
- OpenGL ES 3.x游戏开发(上+下卷)书籍的电子版+源程序
直接附上电子书以及源代码下载链接:https://pan.baidu.com/s/1G10hw5aIi-Bc2LyktwKrdg
- Web网页端IM产品RainbowChat-Web的v7.2版已发布
一.关于RainbowChat-Web RainbowChat-Web是一套Web网页端IM系统,是RainbowChat的姊妹系统(RainbowChat是一套基于开源IM聊天框架 MobileIM ...