题目来源:
题意:至少要多少大的子矩阵 能够覆盖全图
比如例子 能够用一个AB 组成一个
ABABAB
ABABAB 能够多出来
思路:每一行求出周期 总共n个 求这n个周期的最小公倍数 假设大于m 取m
每一列求出周期 总共m个求这个m个周期的最小公倍数 假设大于n取n
答案就是2个最小公倍数的积
#include#include #include #include 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;}