CH1808 Milking Grid

时间:2023-03-08 15:50:04

题意

POJ2185 数据加强版

描述

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.

输入

  • 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.

输出

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

样例输入

2 5

ABABA

ABABA

样例输出

2

提示

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

来源

USACO 2003 Fall

分析

参照maxmercer的题解。

所谓正解?(伪)

  1. 求的所有行的循环节求max值,再求列的循环节的max值,两者相乘.

    反例: 

    2 6

    ABCDAB

    ABCABC 

    用1求出来是8.实际上是12.
  2. 将循环节求最小公倍数,若大于行(列)数就变为行(列)数.

    反例:

    2 8

    ABCDEFAB

    ABABAAAB

    用2算出来因为行的循环节为5,6,最小公倍数30,因为大于8就转化为8,再乘上竖着的2,答案为16.

    实际上答案应该是12,为:

    ABCDEF

    ABABAA

    事实证明,POJ的数据太水了...网上很多题解都是错误的.

正解(真)

我们对与行和列进行hash操作.我们首先将所有列hash,那么每一列变成一个数,也就将矩阵压缩成了一行.再进行kmp的next预处理,求出循环节.再对行hash,列kmp,求出循环节,相乘即可.

正确性?

因为对于一串独立的字符串,他的hash值是唯一的.那么在行kmp的时候一列成了一个数值,那么两列数值相同当且仅当两列字符相同.因为最小矩阵覆盖不会出现错开的情况,是对齐的,那么一列可能穿过多次最小矩阵,那在一个最小矩阵长度之后的那一列,应该是与他相同的,因为我们是对齐了的.对行同理.

时间复杂度\(O(RC)\)

代码

#include<bits/stdc++.h>
typedef unsigned long long ULL;
const int maxn=10005,base=131;
int r,c,ans,len,nxt[maxn];
char s[maxn][105];
ULL temp[maxn],line[maxn],row[maxn];
int kmp_nxt(){
int i=0,j=-1;nxt[0]=-1;
while(i<len){
if(j==-1||temp[i]==temp[j]) ++i,++j,nxt[i]=j;
else j=nxt[j];
}
return len-nxt[len];
}
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
scanf("%d%d",&r,&c);
for(int i=0;i<r;++i) scanf("%s",s[i]);
for(int i=0;i<c;++i) for(int j=0;j<r;++j) line[i]=line[i]*base+s[j][i];
for(int i=0;i<c;++i) temp[i]=line[i];
len=c,ans=kmp_nxt();
for(int i=0;i<r;++i) for(int j=0;j<c;++j) row[i]=row[i]*base+s[i][j];
for(int i=0;i<r;++i) temp[i]=row[i];
len=r,ans*=kmp_nxt();
printf("%d\n",ans);
return 0;
}