poj2185Milking Grid【kmp next数组求循环节】
大意:告诉你一个字符矩阵 然后让你找出一个最小的矩阵 整个矩阵能用该小矩阵去填充, 可以超出边界
例如:
ABABABA
ABABABA
可以用AB去铺满
最后一列A用AB填充 超出边界部分就忽略
分析:
把整个矩阵先按行来看
求出每行字符串的最小循环节 也就是l - next[l]
然后求出他们的最小公倍数 也就是公共的最小循环节 注意要把该倍数与边界作比较 取小值
通过以上 就能求出 用n行用最小公倍数列做区间能把后面几列铺完
用同样的方法对1~最小公倍数列进行求解
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 6 using namespace std; 7 8 void Get(char *s, int *next) { 9 int l = strlen(s); 10 int j = 0, k = -1; 11 next[0] = -1; 12 while(j < l) { 13 if(k == -1 || s[j] == s[k]) { 14 next[++j] = ++k; 15 } else { 16 k = next[k]; 17 } 18 } 19 } 20 const int maxn = 10005; 21 int next[maxn]; 22 23 int Circle(char *s) { 24 Get(s, next); 25 int l = strlen(s); 26 return l - next[l]; 27 } 28 29 char s[maxn][maxn]; 30 char s2[maxn][maxn]; 31 int main() { 32 int n, m; 33 while(EOF != scanf("%d %d",&n, &m) ) { 34 for(int i = 0; i < n; i++) { 35 scanf("\n%s", s[i]); 36 } 37 for(int i = 0; i < n; i++) { 38 for(int j = 0; j < m; j++) { 39 s2[j][i] = s[i][j]; 40 } 41 } 42 int ans = 1; 43 for(int i = 0; i < n; i++) { 44 int x = Circle(s[i]); 45 int y = __gcd(ans, x); 46 ans = ans * x / y; 47 } 48 if(ans > m) ans = m; 49 int sum = 1; 50 for(int i = 0; i < ans; i++) { 51 int x = Circle(s2[i]); 52 int y = __gcd(sum, x); 53 sum = sum * x / y; 54 } 55 if(sum > n) sum = n; 56 printf("%d\n", ans * sum); 57 } 58 }