题目链接
题意:用最小面积的矩形表示完整个区域,可以有多余。
举几个样例:
2 8
ABCDEFAB
AAAABAAA
ans:12
2 9
accaccacc
accaccdac
ans:18
2 9
accaccacc
abcdfsegk
ans:18
2 9
accacacca
accacacca
ans:5
可以大致自己推一下,就会理解了:
再来个:
3 3
asd
asd
ase
ans:9
那么,举完了样例,就是怎么解这道题的问题了,一开始的想法就是利用GCD求最小的横向以及纵向的面积覆盖,但是…… WA了,然后继续想办法,既然是求最大公共周期,那么这一列以及对应的一排,应该有自己的最小周期,(没有就是字符串本身的长了),那么,我们枚举每个字符串的全体周期可能性,然后一一找到最小的即可:具体的话,看一下代码,就是这个意思,表述不清……QAQ
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 1e4 + 5;
int R, C;
char s[maxN][80];
int vis[maxN], nex[maxN];
void cal_nex(int pos)
{
nex[0] = nex[1] = 0;
int k = 0;
for(int i=2; i<=C; i++)
{
while(k>0 && s[pos][k+1] != s[pos][i]) k = nex[k];
if(s[pos][k+1] == s[pos][i]) k++;
nex[i] = k;
}
k = nex[C];
while(k)
{
vis[C - k]++;
k = nex[k];
}
}
void oth_nex(int pos)
{
nex[0] = nex[1] = 0;
int k = 0;
for(int i=2; i<=R; i++)
{
while(k>0 && s[k+1][pos] != s[i][pos]) k = nex[k];
if(s[k+1][pos] == s[i][pos]) k++;
nex[i] = k;
}
k = nex[R];
while(k)
{
vis[R - k]++;
k = nex[k];
}
}
int main()
{
while(scanf("%d%d", &R, &C)!=EOF)
{
memset(vis, 0, sizeof(vis));
for(int i=1; i<=R; i++)
{
scanf("%s", s[i]+1);
cal_nex(i);
}
int ans = C, res = R;
for(int i=1; i<=C; i++) if(vis[i] == R) { ans = i; break; }
memset(vis, 0, sizeof(vis));
for(int i=1; i<=C; i++) oth_nex(i);
for(int i=1; i<=R; i++) if(vis[i] == C) { res = i; break; }
printf("%d\n", ans * res);
}
return 0;
}