POJ P2185 Milking Grid KMP变形

Milking Grid
Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 5372 Accepted: 2249

Description

Every morning when they are milked, the Farmer John's cows form a rectangular grid that is R (1 <= R <= 10,000) rows by C (1 <= C <= 75) columns. As we all know, Farmer John is quite the expert on cow behavior, and is currently writing a book about feeding behavior in cows. He notices that if each cow is labeled with an uppercase letter indicating its breed, the two-dimensional pattern formed by his cows during milking sometimes seems to be made from smaller repeating rectangular patterns. 

Help FJ find the rectangular unit of smallest area that can be repetitively tiled to make up the entire milking grid. Note that the dimensions of the small rectangular unit do not necessarily need to divide evenly the dimensions of the entire milking grid, as indicated in the sample input below. 

Input

* Line 1: Two space-separated integers: R and C 

* Lines 2..R+1: The grid that the cows form, with an uppercase letter denoting each cow's breed. Each of the R input lines has C characters with no space or other intervening character. 

Output

* Line 1: The area of the smallest unit from which the grid is formed 

Sample Input

2 5
ABABA
ABABA

Sample Output

2

Hint

The entire milking grid can be constructed from repetitions of the pattern 'AB'.

Source


这道题真心没思路。。。于是翻题解。

题解链接:http://blog.sina.com.cn/s/blog_69c3f0410100tyjl.html  以下是搬运

题意:在字符矩阵中找出一个最小子矩阵,使其多次复制所得的矩阵包含原矩阵。

在网上找到了好多代码都是能通过部分数据,他们的代码和误点给我以提示。

思路:

支持他们的观点:最小重复矩阵一定靠左上角。

第一步也是找最小重复子矩阵的宽,网上的大部分代码就卡在这里,如实例(poj讨论数据):

实例1:

2 8

ABCDEFAB

AAAABAAA

实例2:

2 8

ABCDEFAB

AAAABABC

误区1:网上的代码找宽的方法(多数代码):用KMP的next求出每行最小重复子串长度,然后求这些长度的公倍数,对于这个实例:第一行为6,第二行为5,6与5的最小公倍数为30,大于8则取8为宽,这种思路对实例2很合适,但明显对于实例1是错误的。(这种思路的AC代码网上有非常多)

误区2:同样用KMP的next求出每行最小重复子串长度,然后取最大的那个长度作为宽,这种对于实例1来说刚好能过,但对于实例2就无能为力了。(这种思路的AC代码网上有比较少)

出现以上误区的博文误倒大家,只能说明POJ数据太弱。

说说我的思路吧:找出每行的重复子串长度的各种可能情况,然后每行都有的并且是最小长度作为宽width。

第二步找最小重复子矩阵的高,这个思路和网上的差不多,取每行的宽为width的前缀作为一个单位,对这0到r-1个单位求出KMP的next函数,找出最小重复子序列的单位数作为高height,最终答案为width*height。

看过他的题解,写了C++代码:

#include <iostream>
using namespace std;

string s[10010],a;
int p[10010],i,j,x,y,r,c,f[80]={0};

int main()
{
	ios::sync_with_stdio(false); //不加会TLE
	cin>>r>>c;
	for (i=0;i<r;++i){
		cin>>s[i];
		a=s[i];
		for (j=c-1;j>0;--j){
			a[j]=0;
			for (x=0,y=0;s[i][y];++x,++y){
				if (!a[x]) x=0;
				if (a[x]!=s[i][y]) break;
			}
			if (!s[i][y]) f[j]++;
		}
	}
	for (i=0;i<c;++i) if (f[i]==r) break;
	x=i;
	for (i=0;i<r;++i) s[i][x]=0;
	p[0]=-1; j=-1;
	for (i=1;i<r;++i){
		while (j>-1 && s[i]!=s[j+1]) j=p[j];
		if (s[i]==s[j+1]) j++;
		p[i]=j;
	}
	cout<<(r-1-p[r-1])*x<<endl;
	return 0;
}

kdwycz的网站:  http://kdwycz.com/

kdwyz的刷题空间:http://blog.csdn.net/kdwycz




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值