Milking Grid
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