题目链接:http://poj.org/problem?id=2185

题目大意:求一个二维的字符串矩阵的最小覆盖子矩阵,即这个最小覆盖子矩阵在二维空间上不断翻倍后能覆盖原始矩阵。

题目分析:next函数的应用。需要枚举每一行每一列的字符串所对应的的 nxt[] 值,然后通过分析计算出最小的宽和最小的高。

具体分析

参考链接:https://blog.csdn.net/u013686535/article/details/52197467

一看这题,容易想出一种很直观的做法:求出每一行的最小重复串长度,取所有行的最小重复串长度的lcm为宽;对列也同样操作求出高。这种想法虽然很直观,但是否正确呢?

事实上,这种算法并不是正确的。如下面的这个反例:

2 8
ABCDEFAB
AAAABAAA

对于这个例子:第一行为6,第二行为5,6与5的最小公倍数为30,大于8则取8为宽,但明显是错误的。

但由于poj的测试数据太弱,以致使用这种方法的程序也可以通过。

下面介绍一下正解的做法。

首先是确定宽度:我们分别求出每行所有可能的重复子串长度,例如对于aaaa就有1、2、3和4,然后取每行都有的重复子串长度中最小的作为宽。

例如,对于上面的例子,第一行的重复子串长度只可能是6或8(显然整个串为一个重复子串也是可以的),第二行则可能是5、6、7或8,那么取它们都有的6和8当中最小值6,就是最小覆盖子矩阵的宽。

然后分成两步:

  • 考虑到每行的列数比较小, 1<=C<=75 ,可以直接暴力枚举重复子串的长度,每列逐一检查是否与当前枚举的重复子串相对应。因此求宽度这个部分的时间复杂度为 O(R*C^2)
  • 找到C以后我们再来一个个枚举R就可以了,时间复杂度也是 O(R*C^2)

不过我这里采用标记的方式,时间复杂度降到 O(R*C)

代码:

#include <iostream>
#include <string>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 404000; int m, nxt[maxn];
string t; int N, M;
char ch[10010][80];
int cnt_c[80], cnt_r[10010]; void cal_next() {
m = t.length();
for (int i = 0, j = -1; i < m; i ++) {
while (j != -1 && t[j+1] != t[i]) j = nxt[j];
nxt[i] = (j+1 < i && t[j+1] == t[i]) ? ++j : -1;
}
} void solve() {
// 首先清空用于记录的cnt_c和cnt_r数组
memset(cnt_c, 0 ,sizeof(cnt_c));
memset(cnt_r, 0, sizeof(cnt_r));
// 遍历每一行
for (int i = 0; i < N; i ++) {
t = "";
for (int j = 0; j < M; j ++) t += ch[i][j];
cal_next();
int j = m-1;
while (nxt[j] != -1) {
j = nxt[j];
cnt_c[m-1-j] ++;
}
}
// 遍历每一列
for (int i = 0; i < M; i ++) {
t = "";
for (int j = 0; j < N; j ++) t += ch[j][i];
cal_next();
int j = m-1;
while (nxt[j] != -1) {
j = nxt[j];
cnt_r[m-1-j] ++;
}
}
// 找到最小的cnt_c[i]==N,没有则M
int cc = 1, rr = 1;
for (; cc < M; cc ++) if (cnt_c[cc] == N) break;
// 找到最小的cnt_r[i]==M,没有则N
for (; rr < N; rr ++) if (cnt_r[rr] == M) break;
cout << rr * cc << endl;
} int main() {
while (cin >> N >> M) {
for (int i = 0; i < N; i ++) cin >> ch[i];
solve();
}
return 0;
}

【KMP】POJ 2185 Milking Grid -- Next函数的应用的更多相关文章

  1. 字符串KMP || POJ 2185 Milking Grid

    求一个最小矩阵,经过复制能够覆盖原矩阵(覆盖,不是填充,复制之后可以有多的) *解法:横着竖着kmp,求最大公倍数的做法是不对的,见http://blog.sina.com.cn/s/blog_69c ...

  2. POJ 2185 Milking Grid KMP循环节周期

    题目来源:id=2185" target="_blank">POJ 2185 Milking Grid 题意:至少要多少大的子矩阵 能够覆盖全图 比如例子 能够用一 ...

  3. [poj 2185] Milking Grid 解题报告(KMP+最小循环节)

    题目链接:http://poj.org/problem?id=2185 题目: Description Every morning when they are milked, the Farmer J ...

  4. POJ 2185 Milking Grid(KMP)

    Milking Grid Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 4738   Accepted: 1978 Desc ...

  5. POJ 2185 Milking Grid [二维KMP next数组]

    传送门 直接转田神的了: Milking Grid Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 6665   Accept ...

  6. POJ 2185 Milking Grid KMP(矩阵循环节)

                                                            Milking Grid Time Limit: 3000MS   Memory Lim ...

  7. POJ 2185 Milking Grid [KMP]

    Milking Grid Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 8226   Accepted: 3549 Desc ...

  8. 题解报告:poj 2185 Milking Grid(二维kmp)

    Description Every morning when they are milked, the Farmer John's cows form a rectangular grid that ...

  9. poj 2185 Milking Grid

    Milking Grid http://poj.org/problem?id=2185 Time Limit: 3000MS   Memory Limit: 65536K       Descript ...

随机推荐

  1. Mysql分布式集群

    一.准备 集群: 192.168.1.191  管理节点192.168.1.192  管理节点192.168.1.193  数据节点和API节点 192.168.1.194  数据节点和API节点 安 ...

  2. BurpSuite安装、使用

    本周学习内容: 1.学习<网络是怎么连接的>和JavaScript: 2.学习MySQL和Linux: 3.熟悉burpsuite: 4.使用wireshark观察数据包: 5.XAMPP ...

  3. Django+element ui前后端不分离的博客程序

    最近把去年写的一个烂尾博客(使用了django1.11和element ui)又重新完善了一下,修改了样式和增加了新功能 github链接:https://github.com/ngauerh/Nag ...

  4. codevs:2849 素数判定 3:输入一个正整数x(3<=x<=100000),判断x是否是质数,如果是质数则输出信息“prime”,否则输出“composite”。

    #include<iostream>#include<cstdio>#include<cmath>using namespace std;int a[2];int ...

  5. 【dp】P1026 统计单词个数

    题目描述 给出一个长度不超过200200的由小写英文字母组成的字母串(约定;该字串以每行2020个字母的方式输入,且保证每行一定为2020个).要求将此字母串分成kk份(1<k \le 401& ...

  6. Ceilometer和Gnocchi的监控架构解析

    1  采集模块整体架构 采集模块主要分为三大块. Ceilometer:用于采集数据并处理数据后发送到gnocchi服务去存储 Gnocchi:用于将采集数据进行计算合并和存储并提供rest api方 ...

  7. 一个简单的setTimeout的问题

    经常使用 setTimeout,并且自己认为也算比较熟悉这个函数的用法. 不过今天碰到了,突然发现自己没有意识到这个问题.于是作为一个记录点,进行巩固一下. var timer = window.se ...

  8. 判断是否是合法的IP地址

    ipv4 import re #简单的匹配给定的字符串是否是ip地址,下面的例子它不是IPv4的地址,但是它满足正则表达式 if re.match(r"^(?:[0-9]{1,3}\.){3 ...

  9. CF1187F Expected Square Beauty(期望)

    题目 CF1187F Expected Square Beauty 做法 \(B(x)=\sum\limits_{i=1}^n I_i(x),I_i(x)=\begin{cases}1&x_i ...

  10. 学习DB2之Linux环境下下载

    一 下载前的注册IBM地址:https://www-01.ibm.com/marketing/iwm/iwm/web/pick.do?source=swg-db2expressc&S_PKG= ...