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又耍畸形了!!他要当飞行员,他拿到了一个飞行员测试难度序列,他设定了一个难度差的最大值,在序列中他想找到一个最长的子串,任意两个难度差不会超过他设定的最大值.耍畸形一个人是 ...
随机推荐
- Linux中同步与异步、阻塞与非阻塞概念以及五种IO模型
1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...
- UIAutomator输入中文
之前一直是英文的测试环境,包括手机也是英文的,app也是英文的,涉及不到中文输入法的东西.但现在在写中文的app,所以需要输入中文.看到网上的解决办法如下: 下载https://github.com/ ...
- Leetcode 427.建立四叉树
建立四叉树 我们想要使用一棵四叉树来储存一个 N x N 的布尔值网络.网络中每一格的值只会是真或假.树的根结点代表整个网络.对于每个结点, 它将被分等成四个孩子结点直到这个区域内的值都是相同的. 每 ...
- [python学习篇] [os模块] [2]删除文件夹
def deleteDirectory(self,current_path): if not os.path.exists(current_path): self.logger.info(curren ...
- hihoCoder挑战赛29
多打打不同的比赛,找经验啊 题目4 : 不上升序列 时间限制:40000ms 单点时限:2000ms 内存限制:256MB 描述 给定一个长度为 n 的非负整数序列 a[1..n]. 你每次可以花费 ...
- POJ 2355 Railway tickets
Railway tickets Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 2472 Accepted: 865 De ...
- Linux Shell系列教程之(八)Shell printf命令详解
本文是Linux Shell系列教程的第(八)篇,更多shell教程请看:Linux Shell系列教程 在上一篇:Linux Shell系列教程之(七)Shell输出这篇文章中,已经对Shell p ...
- ubuntu 安装tomcat<服务器>
一.下载tomcat 可以先下载到本地,然后ftp到服务器 官方 Apache Tomcat 的下载页面(下面的链接是apache自己的镜像服务器的地址,不同网络连接的话,apache会给出不同的镜像 ...
- HUST——1103Party(拓扑排序+个人见解)
1103: Party Time Limit: 2 Sec Memory Limit: 64 MB Submit: 11 Solved: 7 Description N students were ...
- [TJOI2017] 城市 (树的直径,贪心)
题目链接 Solution 这道题,调了我一晚上... 一直80分 >_<|| ... 考虑到几点: 分开任意一条边 \(u\) ,那么其肯定会断成两棵树. 肯定是分开直径上的边最优,否则 ...