版权声明:本文为博主原创作品, 转载请注明出处! https://blog.csdn.net/solider98/article/details/83860313
思路分析:
设给定图形可由AB子矩形重复而成, 稍一想便知, 给定图形必定可由其最左上角的AB子矩形重复而成. 因此只需找到所有行(长度C)同时满足S[1...k] = S[C - k + 1...C]的最大的k和所有列(长度为R)同时满足T[1...m] = T[R - m + 1...R]的最大的m, 即为最小循环单元的面积, 具体实现如下AC代码所示:
//POJ2185_Milking Grid
#include <iostream>
#include <cstdio>
#include <set>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXR = 1e4 + 5, MAXC = 80;
char g[MAXR][MAXC]; int R, C;
int rnext[MAXR][MAXC], cnext[MAXC][MAXR];//rnext:行next, cnext: 列next
int cntNext[MAXR];//cntNext[i]:next[i]的个数
int main(){
scanf("%d %d", &R, &C);
for(int i = 1; i <= R; ++i) scanf("%s", g[i] + 1);
//计算行next
for(int i = 1; i <= R; ++i){
rnext[i][1] = 0;
for(int j = 2; j <= C; ++j){
int t = rnext[i][j - 1];
while(t && g[i][t + 1] != g[i][j]) t = rnext[i][t];
if(t > 0) rnext[i][j] = t + 1;
else rnext[i][j] = g[i][1] == g[i][j]? 1: 0;
}
}
//计算列next
for(int i = 1; i <= C; ++i){
cnext[i][1] = 0;
for(int j = 2; j <= R; ++j){
int t = cnext[i][j - 1];
while(t && g[t + 1][i] != g[j][i]) t = cnext[i][t];
if(t > 0) cnext[i][j] = t + 1;
else cnext[i][j] = g[1][i] == g[j][i]? 1: 0;
}
}
//计算行next交集
for(int i = 1; i <= R; ++i)
for(int t = rnext[i][C]; t; ++cntNext[t], t = rnext[i][t]);
int rlen = C;
for(int i = C; i >= 1; --i)
if(cntNext[i] == R){
rlen = C - i; break;
}
memset(cntNext, 0, sizeof(cntNext));
for(int i = 1; i <= C; ++i)
for(int t = cnext[i][R]; t; ++cntNext[t], t = cnext[i][t]);
int clen = R;
for(int i = R; i >= 1; --i)
if(cntNext[i] == C){
clen = R - i; break;
}
cout << clen * rlen << endl;
return 0;
}