[POJ]2185 真正的正解

Milking Grid
Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 8812 Accepted: 3839

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

[Submit]   [Go Back]   [Status]   [Discuss]

Home Page   Go Back  To top


所谓正解?(伪)

    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的时候一列成了一个数值,那么两列数值相同当且仅当两列字符相同.因为最小矩阵覆盖不会出现错开的情况,是对齐的,那么一列可能穿过多次最小矩阵,那在一个最小矩阵长度之后的那一列,应该是与他相同的,因为我们是对齐了的.对行同理.
    话说要是不对齐该怎么搞...

代码

#include<stdio.h>
#include<cstring>
const int maxn=10005;
unsigned long long base=10007;
int T,r,c,ans,len,nxt[maxn];
char s[maxn][105];
unsigned long long temp[maxn],line[maxn],row[maxn];
inline 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];
}
inline void solve(){
	scanf("%d%d",&r,&c);
    for(register 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);
}
int main(){
    solve();
}


     
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值