Milking Grid
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 10417 | Accepted: 4508 |
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
思路:
本题让求最小的循环节(是一个矩阵),它可把整个矩阵覆盖
横向:
每一行的最小循环节求出来,然后求所有行的最小循环节长度的公倍数,若>列数,则取列数,但这种做法还有bug,比如:
ABCDEFAB(循环节是ABCDEF,位数为6)
AAAABAAA(循环节是AAAAB,位数为5)
所以只要长度大于最小循环节的循环一次就能覆盖,比如AAAABAAA
AAAAB,AAAABA,AAAABAA,AAAABAAA循环都可以
所以取6,也就说,6,7,8和5,6,7,8重合的最小的数
纵向:
把一行看成一个字符串,如
s1
s2
s3
…
这样对s1,s2,s3……求kmp,和循环节
注意char s[N]和char s1[N]之间的比较要用strcmp函数:
s1<s2时,返回负数;
s1==s2时,返回0
s1>s2,返回正数
答案是横向和纵向的循环节位数相乘
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef pair<int,int>P;
const int INF=0x3f3f3f3f;
const int N=10015;
char s[N][100];
int nex[N];
int R,C,ans_c=0,ans_r;
void getRNext(char s[]){
nex[0]=-1;
nex[1]=0;
int len=strlen(s);
for(int i=2;i<=len;i++){
int k=nex[i-1];
while(k>=0&&s[k-1+1]!=s[i-1])k=nex[k];
nex[i]=k+1;
}
ans_c=max(ans_c,len-nex[len]);
}
void getCNext(){
nex[0]=-1;
nex[1]=0;
for(int i=2;i<=R;i++){
int k=nex[i-1];
while(k>=0&&strcmp(s[k-1+1],s[i-1]))k=nex[k];
nex[i]=k+1;
}
ans_r=R-nex[R];
}
int main(){
scanf("%d%d",&R,&C);
for(int i=0;i<R;i++){
scanf("%s",s[i]);
}
for(int i=0;i<R;i++){
getRNext(s[i]);
}
getCNext();
printf("%d\n",ans_c*ans_r);
}