BZOJ 2085 [POI2010] Hamsters
题面
Description
Tz养了一群仓鼠,他们都有英文小写的名字,现在Tz想用一个字母序列来表示他们的名字,只要他们的名字是字母序列中的一个子串就算,出现多次可以重复计算。现在Tz想好了要出现多少个名字,请你求出最短的字母序列的长度是多少。
Input
输入:第一行n(1<=n<=200)和m(1<=m<=10的9此方),n表示有多少个仓鼠,m表示Tz希望出现名字的次数,接下来n行,每行都是仓鼠的名字(中间没有空格)。
Output
输出:一行,最短的字母序列的长度。
Sample Input
4 5
monika
tomek
szymon
bernard
Sample Output
23
Sample Output
23
题目大意
略.
题解
这一题的题面漏了一个条件: 字符串之间两两不相包含. 由于\(n \le 200\), 不难想到让这些名字两两作一次KMP, 得到一个转移矩阵. 我们考虑如何让\(m\)个名字在所求的串中出现. 建立一个初始矩阵: 对角线为每个字符串的长度, 其余位置均为\(+\infty\). 对初始矩阵与转移矩阵作\(m - 1\)次转移(使用倍增的方法, 类似于快速幂, 但不是矩阵乘法, 而是对应的行向量和列向量加起来取\(\min\)值). 得到的矩阵中, \(res_{i j}\)表示开始第一个名字为\(i\), 最后出现的名字为\(j\)的需要的最少字符数量.
在\(res_{n \times n}\)中取min即可.
一些细节需要注意, 已经在代码中标注.
#include <cstdio>
#include <cstring>
#include <algorithm>
const int N = 200, LEN = (int)1e5;
const long long INF = (long long)1e15;
namespace KMP
{
inline void initialize(char *str, int len, int *pre)
{
pre[0] = -1;
for(int i = 1; i < len; ++ i)
{
int p = pre[i - 1];
for(; ~ p && str[p + 1] ^ str[i]; p = pre[p]);
if(str[p + 1] == str[i])
++ p;
pre[i] = p;
}
}
inline int match(char *s, int len, char *t, int *pre)
{
int p = -1;
for(int i = 0; i < len; ++ i)
{
for(; ~ p && t[p + 1] ^ s[i]; p = pre[p]); // 假如s和t是同一个串的话, 则要特判
if(t[p + 1] == s[i] && (s != t || p + 1 < i))
++ p;
}
return p + 1;
}
}
struct matrix
{
long long a[N][N];
int n;
inline matrix(int _n)
{
n = _n;
}
inline matrix friend operator *(const matrix &A, const matrix &B)
{
static matrix res(A.n);
for(int i = 0; i < A.n; ++ i)
for(int j = 0; j < A.n; ++ j)
{
res.a[i][j] = INF;
for(int k = 0; k < A.n; ++ k)
res.a[i][j] = std::min(A.a[i][k] + B.a[k][j], res.a[i][j]);
}
return res;
}
};
inline void power(matrix A, int x, matrix &res)
{
for(; x; x >>= 1, A = A * A)
if(x & 1)
res = res * A;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("BZOJ2085.in", "r", stdin);
// freopen("BZOJ2085.out", "w", stdout);
#endif
int n, m;
scanf("%d%d", &n, &m);
static char str[N][LEN];
static int pre[N][LEN];
for(int i = 0; i < n; ++ i)
scanf("%s", str[i]), KMP::initialize(str[i], strlen(str[i]), pre[i]);
static matrix A(n);
for(int i = 0; i < n; ++ i)
for(int j = 0; j < n; ++ j)
A.a[i][j] = strlen(str[j]) - KMP::match(str[i], strlen(str[i]), str[j], pre[j]);
static matrix res(n);
for(int i = 0; i < n; ++ i)
for(int j = 0; j < n; ++ j)
res.a[i][j] = i ^ j ? INF : strlen(str[i]);
power(A, m - 1, res); // m要减1
long long ans = INF;
for(int i = 0; i < n; ++ i)
for(int j = 0; j < n; ++ j)
ans = std::min(ans, res.a[i][j]);
printf("%lld", ans);
}
BZOJ 2085 [POI2010] Hamsters的更多相关文章
- BZOJ 2085 luogu P3502 [POI2010]Hamsters (KMP、Floyd、倍增)
数组开小毁一生-- 题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2085 这题在洛谷上有个条件是"互不包含",其实 ...
- BZOJ 2080: [Poi2010]Railway 双栈排序
2080: [Poi2010]Railway Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 140 Solved: 35[Submit][Statu ...
- [poi2010]Hamsters
题意:Tz养了一群仓鼠,他们都有英文小写的名字,现在Tz想用一个字母序列来表示他们的名字,只要他们的名字是字母序列中的一个子串就算,出现多次可以重复计算.现在Tz想好了要出现多少个名字,请你求出最短的 ...
- BZOJ 2096: [Poi2010]Pilots( set )
用个set维护就可以水过去...O(NlogN) 应该可以用单调队列O(N).... --------------------------------------------------------- ...
- BZOJ 2096([Poi2010]Pilots-单调队列-差值)
2096: [Poi2010]Pilots Time Limit: 30 Sec Memory Limit: 162 MB Submit: 190 Solved: 97 [ Submit][ ...
- bzoj 2095: [Poi2010]Bridges [混合图欧拉回路]
2095: [Poi2010]Bridges 二分答案,混合图欧拉路判定 一开始想了一个上下界网络流模型,然后发现不用上下界网络流也可以 对于无向边,强制从\(u \rightarrow v\),计算 ...
- BZOJ 2084: [Poi2010]Antisymmetry [Manacher]
2084: [Poi2010]Antisymmetry Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 609 Solved: 387[Submit] ...
- BZOJ 2083: [Poi2010]Intelligence test [vector+二分]
2083: [Poi2010]Intelligence test Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 469 Solved: 227[Su ...
- 【刷题】BZOJ 2096 [Poi2010]Pilots
Description Tz又耍畸形了!!他要当飞行员,他拿到了一个飞行员测试难度序列,他设定了一个难度差的最大值,在序列中他想找到一个最长的子串,任意两个难度差不会超过他设定的最大值.耍畸形一个人是 ...
随机推荐
- IDEA入门学习笔记1:资料收集
IDEA2018软件下载 :https://mp.weixin.qq.com/s?__biz=MzIwMjE1MjMyMw==&mid=2650200056&idx=1&sn= ...
- Python之简单Socket编程
Socket编程这块儿还是比较重要的,记录一下:实现服务器端和客户端通信(客户端发送系统指令,如ipconfig等,服务器端执行该指令,然后将指令返回结果给客户端再传过去,设置一次最多直接收1024字 ...
- cf 1016C
C. Vasya And The Mushrooms time limit per test 2 seconds memory limit per test 256 megabytes input s ...
- JS中如何操作数组
背景:随笔中所应用到的代码来自于上一篇随笔,MVC&JQuery如何根据List动态生成表格,部分代码不再重复. 代码如下: $("#btnTan").click(func ...
- CF 219 D:Choosing Capital for Treeland(树形dp)
D. Choosing Capital for Treeland 链接:http://codeforces.com/problemset/problem/219/D The country Tre ...
- python基础学习笔记——列表及元组
列表 列表的介绍 列表是python的基础数据类型之一 ,其他编程语言也有类似的数据类型. 列表的索引和切片 列表和字符串一样也拥有索引: lst = ['刘德华','周润发','周杰伦','向华强 ...
- Apache下error.log文件太大的处理方法
清除error.log.access.log并限制Apache日志文件大小的方法,在网上搜了下相应的资料,并按照如下步骤做了一遍,网站恢复正常 清除error.log.access.log并限制A ...
- 06-python进阶-多线程下载器练手
我们需要用python 写一个多线程的下载器 我们要先获取这个文件的大小 然后将其分片 然后启动多线程 分别去下载 然后将其拼接起来 #!/usr/bin/env python#coding:utf- ...
- 序列化 pickle & json & shelve
把内存数据转成字符,叫序列化,dump,dumps 把字符转成内存数据类型,叫反序列化load,loads dumps:仅转成字符串 dump不仅能把对象转换成str,还能直接存到文件内 json.d ...
- WIN下C开发环境搭建
安装编译器 MinGW提供了一套简单方便的Winodows下的基于GCC程序开发环境 官网下载安装 http://www.mingw.org/ 打开后选择basic setup的package Ins ...