洛谷P3502 [POI2010]CHO-Hamsters感想及题解(图论+字符串+矩阵加速\(dp\&Floyd\))

标签:题解

阅读体验:https://zybuluo.com/Junlier/note/1310683

扯闲谈

觉得这是道比较好的引导模型转换的题,就决定写一篇题解

即使我就是看的ZSY的,并且几乎写的一模一样(还是稍有不同的)

安利一发租酥雨的题解

原题地址:洛谷P3502 [POI2010]CHO-Hamsters

先理解题意

给出\(n\)个字符串,让你用这\(n\)个字符串拼接起来,使\(n\)个字符串总的出现次数至少为\(m\),问拼接起来的字符串的最短长度是多少(\(n=200,m=100000\))

很容易想到一个\(n^2m\)的\(dp\)

先用\(KMP\)跑出每个字符串接在其他字符串后面的最小代价(增加的最短长度)记为\(dis\)数组

dp[k][i]表示已经出现了\(k\)个字符串且最后一个字符串是\(i\)号串的最短长度

显然直接\(dp\)就行了吧,放一段代码

for(int i=1;i<=n;i++)
dp[1][i]=len[i];
for(int k=2;k<=m;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dp[k][i]=min(dp[k][i],dp[k-1][j]+dis[j][i]);

\[显然\min_{i=1}^{n}dp[m][i]就是答案了
\]

转换题型

看到上面那一段转移是不是神似\(Floyd\)?(好吧其实我已开始并不这么觉得)

我们把每个字符串抽象成图上的一个点,原来求出的\(dis\)数组看做每对点之间的边(权)

那么是不是我们的问题就转化成了在图上跑\(m\)个点的最短距离

很容易发现为什么上面的\(dp\)那么像\(Floyd\)了。。。

因为存在边界情况:所有字符作为开头时它的代价是len[i]

所以\(dis\)数组相对应有以下更新(新建一个\(0\)号点表示开始节点):dis[0][i]=len[i],dis[i][0]=Inf

矩阵加速

不能完全叫矩阵,只是比较像

考虑到\(dp\)的每一次转移都是一遍\(Floyd\)(每一次转移都是一样的)

你想到了什么?矩阵快速幂优化\(dp!\)

我们之前的矩阵优化都是通过矩阵之间的运算实现的

我们今天运用一个假的运算法则,它叫做\(Floyd\)矩阵运算法则

对于每一次的矩阵乘法改成一次\(Floyd\)运算,就可以顺利的把我们的\(100000\)级别的\(m\)优化掉

也许你还是没有明白为什么可以把\(Floyd\)直接套进矩阵去优化

其实归根结底还是这个转移是没有变化的,且满足结合律

所以进行了很多遍的\(Floyd\)可以直接再和\(ans\)相“乘”(\(ans\)就是答案矩阵了)

代码

洛谷上不开\(O_2\)还是会\(TLE\)。。。

#include<bits/stdc++.h>
#define il inline
#define rg register
#define ldb double
#define lst long long
#define rgt register int
#define N 250
#define M 100050
using namespace std;
const lst Inf=1e18;
il int read()
{
int s=0,m=0;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')m=1;ch=getchar();}
while( isdigit(ch))s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
return m?-s:s;
} int n,m;
int len[N];
int Nxt[N][M];
char S[N][M];
lst Ans=Inf;
struct Matrix{
lst f[N][N];
Matrix operator*(const Matrix K)const
{
Matrix mid;
memset(mid.f,63,sizeof(mid.f));
for(rgt k=0;k<=n;++k)
for(rgt i=0;i<=n;++i)
for(rgt j=0;j<=n;++j)
mid.f[i][j]=min(mid.f[i][j],f[i][k]+K.f[k][j]);
return mid;
}
}dis,ans; il void Get_dis()
{
for(rgt k=1;k<=n;++k)
for(rgt i=2,j=0;i<=n;++i)
{
while(j&&S[k][i]!=S[k][j+1])j=Nxt[k][j];
if(S[k][i]==S[k][j+1])++j;
Nxt[k][i]=j;
}
//预处理KMP的Nxt[]
dis.f[0][0]=Inf;
for(rgt x=1;x<=n;++x)
{
dis.f[0][x]=len[x],dis.f[x][0]=Inf;
for(rgt y=1;y<=n;++y)
for(rgt i=2,j=0;i<=len[x];++i)
{
while(j&&S[y][j+1]!=S[x][i])j=Nxt[y][j];
if(S[y][j+1]==S[x][i])++j;
if(i==len[x])dis.f[x][y]=len[y]-j;
}
}//预处理两个字符串转化的最小长度
} int main()
{
n=read(),m=read()-1;
for(rgt i=1;i<=n;++i)
scanf(" %s ",S[i]+1),len[i]=strlen(S[i]+1);
Get_dis(),ans=dis;
while(m)
{
if(m&1)ans=ans*dis;
dis=dis*dis,m>>=1;
}
for(rgt i=1;i<=n;++i)
Ans=min(Ans,ans.f[0][i]);
printf("%lld\n",Ans);return 0;
}

总结一下

模型转化还是比较重要的

考场上几次都没有想到

像遇到这种转化有代价,有要求最小代价的题目

就可以往最短路方面去转化

而遇到\(dp\)无法优化又有转移方程不变这种性质时

可以考虑矩阵快速幂优化\(dp\)

洛谷P3502 [POI2010]CHO-Hamsters感想及题解(图论+字符串+矩阵加速$dp\&Floyd$)的更多相关文章

  1. 【字符串】【hash】【倍增】洛谷 P3502 [POI2010]CHO-Hamsters 题解

        这是一道字符串建模+图论的问题. 题目描述 Byteasar breeds hamsters. Each hamster has a unique name, consisting of lo ...

  2. 洛谷 P3239 / loj 2112 [HNOI2015] 亚瑟王 题解【期望】【DP】

    ???看不懂的期望DP 题目描述 小 K 不慎被 LL 邪教洗脑了,洗脑程度深到他甚至想要从亚瑟王邪教中脱坑. 他决定,在脱坑之前,最后再来打一盘亚瑟王.既然是最后一战,就一定要打得漂亮.众所周知,亚 ...

  3. 洛谷 P4269 / loj 2041 [SHOI2015] 聚变反应炉 题解【贪心】【DP】

    树上游戏..二合一? 题目描述 曾经发明了零件组装机的发明家 SHTSC 又公开了他的新发明:聚变反应炉--一种可以产生大量清洁能量的神秘装置. 众所周知,利用核聚变产生的能量有两个难点:一是控制核聚 ...

  4. 洛谷P1484 种树&洛谷P3620 [APIO/CTSC 2007]数据备份 题解(堆+贪心)

    洛谷P1484 种树&洛谷P3620 [APIO/CTSC 2007]数据备份 题解(堆+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/132 ...

  5. [洛谷P3501] [POI2010]ANT-Antisymmetry

    洛谷题目链接:[POI2010]ANT-Antisymmetry 题目描述 Byteasar studies certain strings of zeroes and ones. Let be su ...

  6. LOJ 2743(洛谷 4365) 「九省联考 2018」秘密袭击——整体DP+插值思想

    题目:https://loj.ac/problem/2473 https://www.luogu.org/problemnew/show/P4365 参考:https://blog.csdn.net/ ...

  7. 洛谷P3387 【模板】缩点 题解

    背景 今天\(loj\)挂了,于是就有了闲情雅致来刷\(luogu\) 题面 洛谷P3387 [模板]缩点传送门 题意 给定一个\(n\)个点\(m\)条边有向图,每个点有一个权值,求一条路径,使路径 ...

  8. [NOI导刊2010提高&洛谷P1774]最接近神的人 题解(树状数组求逆序对)

    [NOI导刊2010提高&洛谷P1774]最接近神的人 Description 破解了符文之语,小FF开启了通往地下的道路.当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某 ...

  9. [洛谷P1029]最大公约数与最小公倍数问题 题解(辗转相除法求GCD)

    [洛谷P1029]最大公约数与最小公倍数问题 Description 输入二个正整数x0,y0(2<=x0<100000,2<=y0<=1000000),求出满足下列条件的P, ...

随机推荐

  1. 5433. 【NOIP2017提高A组集训10.28】图

    题目描述 Description 有一个n个点A+B条边的无向连通图,有一变量x,每条边的权值都是一个关于x的简单多项式,其中有A条边的权值是k+x,另外B条边的权值是k-x,如果只保留权值形如k+x ...

  2. vue父组件更新,子组件也更新的方法

    1.父组件 使用 Math.ramdom() 2.子组件获取 然后监听这个ramdom变化,处理子组件的更新

  3. 微信小程序支付功能讲解

    前言:虽然小程序做过很多,但是一直觉得微信支付功能很是神秘,现在终于有机会接触心里还是有点小激动的,经过一番折腾发现支付也不过如此,在此记录下支付功能的实现过程 小程序的官方文档介绍到发起微信支付即调 ...

  4. 【rust】rust安装,运行第一个Rust 程序 (1)

    安装 Rust 在 Unix 类系统如 Linux 和 macOS 上,打开终端并输入: curl https://sh.rustup.rs -sSf | sh 回车后安装过程出现如下显示: info ...

  5. 怎么实现超大文件上传 2-3GB

    1 背景 用户本地有一份txt或者csv文件,无论是从业务数据库导出.还是其他途径获取,当需要使用蚂蚁的大数据分析工具进行数据加工.挖掘和共创应用的时候,首先要将本地文件上传至ODPS,普通的小文件通 ...

  6. NOI 2727:仙岛求药 x

    总时间限制:  1000ms 内存限制:  65536kB 描述 少年李逍遥的婶婶病了,王小虎介绍他去一趟仙灵岛,向仙女姐姐要仙丹救婶婶.叛逆但孝顺的李逍遥闯进了仙灵岛,克服了千险万难来到岛的中心,发 ...

  7. Ubuntu redis 实战 持久化策略 主从复制 以及 故障恢复

    推荐文章 redis数据结构学习 redis持久化 redis主从复制 redis哨兵

  8. 【bzoj3262】陌上花开

    题目描述: 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当且仅当Sa& ...

  9. 获取浏览区变化的方法resize() 方法

    当调整浏览器窗口的大小时,发生 resize 事件. resize() 方法触发 resize 事件,或规定当发生 resize 事件时运行的函数. <html> <head> ...

  10. 语法检查程序LanguageTool学习和使用笔记

    这是LanguageTool的官方语法规则说明,一定要仔细研究,学会这个语法,就可以自己编写语法检查规则了,这篇文档上说,编写这份语法检查文档,你甚至都不需要是一名程序员: http://wiki.l ...