题意:给出一个大矩阵,求最小覆盖矩阵,大矩阵可由这个小矩阵拼成。(就如同拼磁砖,允许最后有残缺)

正确解法的参考链接:
http://poj.org/showmessage?message_id=153316
http://blog.sina.com.cn/s/blog_69c3f0410100tyjl.html

在discuss里还看到有人说可以这么简化:
求横向最小长度时每次比较整列
求纵向最小长度时每次比较整行
真的是太神了!
http://poj.org/showmessage?message_id=168710

一开始,我也是按照错误的解法来求得。
也就是用KMP的next求出每行的最小循环子串长度,然后求这些长度的公倍数,作为宽(若大于col,则为col)。
然后用KMP的next求出每列的最小循环子串长度,然后求出这些长度的公倍数,作为长(若大于row,则为row)。
这种解法是过不了下面的样例的:
Input
2 8
ABCDEFAB
ABCDEABC
2 8
ABCDEFAB
AAAABAAA

Output
16
12
对于第一个样例,可以这么做。但对于第二个样例,就不行了。
因为AAAABAAA它的循环子串可以理解为AAAAB,也可以理解为AAAABA,AAAABAA,AAAABAAA
而这里取AAAABA,正好与第一行的ABCDEF同样为6,所以答案为12。
但是这样的解法也可以AC,说明POJ数据比较弱。

思路:先用KMP的next函数求出每行的最小循环子串的长度L,那么L,2L,3L,...都可以作为该行的循环子串。
     此外,还可以存在像AAAABAAA的情况。
     设m为mL<=col的最大值,那么由于列最多75,直接通过暴力比较,判断1...mL+1~col是否可以作为循环子串。
     至于如何获取所求最小矩阵的宽度,这里采用http://poj.org/showmessage?message_id=153316的方法,
        用一个数组统计长度出现的次数,最后从小到大遍历一遍,若出现次数为row的长度,即为我们所求的宽度。
        至于高度的话,用KMP的next,每次比较整行,即可求得最小矩阵的高度。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm> using namespace std;
const int maxr=;
const int maxc=;
char grid[maxr][maxc]; //大矩阵
int row,col;//行和列
int rnext[maxr][maxc]; //rnext[i]:对应第i行字符串的next函数
int cnext[maxr]; //求纵向的next,每次比较的是整行
int rlen[maxr]; //rlen[i]:第i行字符串的最小循环子串的长度
int cnt[maxc];//cnt[i]:统计各宽度出现的次数
int ans_c,ans_r; //最小覆盖矩阵的宽度和高度
void rgetNext(int r,char*str){
int k=;
rnext[r][]=;
for(int i=;i<col;i++){
while(k&&str[k]!=str[i])
k=rnext[r][k];
if(str[k]==str[i])
k++;
rnext[r][i+]=k;
}
rlen[r]=col-rnext[r][col];
int i;
for(i=rlen[r];i<=col;i+=rlen[r]){
cnt[i]++;
}
i-=rlen[r];
//直接通过比较来判断,是否还有可能存在的串,如aaabcaaa,除了5,还可能为6,7,8
//即判断第i+1个字符后的后缀是否和前缀相同
for(int j=i+;j<=col;j++){
int x=,y=j;//分别从索引0和y处开始比较
while(str[x]==str[y]){
x++;y++;
}
if(y==col)
cnt[j]++;
}
} void cgetNext(){
int k=;
cnext[]=;
for(int i=;i<row;i++){
while(k&& strcmp(grid[k],grid[i])!=)
k=cnext[k];
if(strcmp(grid[k],grid[i])==)
k++;
cnext[i+]=k;
}
ans_r=row-cnext[row];
} int main()
{
scanf("%d%d",&row,&col);
for(int i=;i<row;i++)
scanf("%s",grid[i]);
memset(cnt,,sizeof(cnt));
for(int i=;i<row;i++)
rgetNext(i,grid[i]);
cgetNext();
for(int i=;i<=col;i++){
if(cnt[i]==row){
ans_c=i;
break;
}
}
printf("%d\n",ans_c*ans_r);
return ;
}

POJ 2185 Milking Grid (KMP,求最小覆盖子矩阵,好题)的更多相关文章

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

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

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

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

  3. POJ 2185 Milking Grid [KMP]

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

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

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

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

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

  6. 【KMP】POJ 2185 Milking Grid -- Next函数的应用

    题目链接:http://poj.org/problem?id=2185 题目大意:求一个二维的字符串矩阵的最小覆盖子矩阵,即这个最小覆盖子矩阵在二维空间上不断翻倍后能覆盖原始矩阵. 题目分析:next ...

  7. POJ 2185 Milking Grid(KMP)

    Milking Grid Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 4738   Accepted: 1978 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. 字符串KMP || POJ 2185 Milking Grid

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

随机推荐

  1. XAML(2) - 依赖属性

    3.依赖属性 在用WPF编程时,常常会遇到"依赖属性"这个术语.WPF元素是带有方法,属性和事件的类.WPF元素的几乎每个属性都是依赖属性, 这是什么意思?依赖属性可以依赖其他输入 ...

  2. 数组(Array),二维数组,三维数组

    数组(Array):相同类型数据的集合就叫做数组. (一)定义数组的方法: A) type[] 变量名 = new type[数组中元素的个数] 例如: int[] a = new int[10] ; ...

  3. 从数组->ArrayList->List 为了方便与安全在不断变化着

    在C#中,当我们想要存储一组对象的时候,就会想到用数组,ArrayList,List这三个对象了. 数组 优点优点之一:数组在内存中是连续存储的,所以它的索引速度是非常的快,而且赋值与修改元素也很简单 ...

  4. 【EF Code First】CodeFirst初始配置

    1,在Nuget管理中下载EntityFramework 2,配置文件中添加数据库配置 <connectionStrings> <add name="DefaultConn ...

  5. maven学习手记 - 2

    学习目标 maven 的插件和目标: maven 的生命周期和阶段.   前言 在手记1中看到执行 mvn clean package 时,maven 自动执行了compile 和 test 操作. ...

  6. C Primer Plus学习笔记(二)

    1. C的左值用是指用于标志一个特定的数据对象的名字或表达式.“数据对象”是泛指数据存储的术语. 赋值运算符的左边应该是以个可以修改的左值. 右值是指可赋给可修gia的左值的量.右值可以是常量.变量或 ...

  7. Protocol-SPI协议

    说明.文章摘自:SPI协议及其工作原理浅析 http://bbs.chinaunix.net/thread-1916003-1-1.html 一.概述. SPI,Serial Peripheral I ...

  8. 我教女朋友学编程html系列(7)—Html无序列表、自定义列表、有序列表及常用例子

    昨天写的那篇文章<我教女朋友学编程Html系列(6)—Html常用表单控件>,基本上有1000人左右看了,那边文章是我站在前人的肩膀上修改来的,添加了截图和说明,合并了例子,使之更容易被初 ...

  9. Careercup - Microsoft面试题 - 5175246478901248

    2014-05-11 23:52 题目链接 原题: design an alarm clock for a deaf person. 题目:为聋人设计闹钟? 解法:聋人听不见,那么闪光.震动都可行.睡 ...

  10. Careercup - Google面试题 - 4847954317803520

    2014-05-08 21:33 题目链接 原题: largest number that an int variable can fit given a memory of certain size ...