首页 > 代码库 > POJ 2185 Milking Grid KMP循环节周期

POJ 2185 Milking Grid KMP循环节周期

题目来源:POJ 2185 Milking Grid

题意:至少要多少大的子矩阵 可以覆盖全图

例如样例 可以用一个AB 组成一个

ABABAB

ABABAB 可以多出来

 

思路:每一行求出周期 总共n个 求这n个周期的最小公倍数 如果大于m 取m

           每一列求出周期 总共m个求这个m个周期的最小公倍数 如果大于n取n

答案就是2个最小公倍数的积

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
using namespace std;
const int maxn = 10010;
char a[maxn][77];
char b[77][maxn]; 
int f[maxn][77];
int f2[77][maxn];
int gcd(int a, int b)
{
	return b?gcd(b, a%b):a;
}
void getFail(char* p, int* f)
{
	int m = strlen(p);
	f[0] = f[1] = 0;
	for(int i = 1; i < m; i++)
	{
		int j = f[i];
		while(j && p[i] != p[j])
			j = f[j];
		f[i+1] = p[i] == p[j] ? j+1 : 0;
	}
}

int main()
{
	int n, m;
	scanf("%d %d", &n, &m);
	for(int i = 1; i <= n; i++)
	{
		scanf("%s", a[i]);
		getFail(a[i], f[i]);
	}
	for(int i = 0; i < m; i++)
	{
		for(int j = 1; j <= n; j++)
		{
			b[i+1][j-1] = a[j][i];
		}	
		b[i+1][n] = 0;
	}
	for(int i = 1; i <= m; i++)
		getFail(b[i], f2[i]);
	int ans1 = 1, ans2 = 1;
	for(int i = 1; i <= n; i++)
	{
		ans1 = ans1/gcd(ans1, m-f[i][m])*(m-f[i][m]);
		if(ans1 > m)
		{
			ans1 = m;
			break;
		}
	}
	for(int i = 1; i <= m; i++)
	{
		ans2 = ans2/gcd(ans2, n-f2[i][n])*(n-f2[i][n]);
		if(ans2 > n)
		{
			ans2 = n;
			break;
		}
	}
	printf("%d\n", ans1*ans2);
	return 0;
}