题目链接: http://poj.org/problem?id=2185
题意: 给出一个矩形字符块, 求能组成该矩形块的最小子矩形块.
思路: 将每行字符串当作一个字符,那么原矩形字符块就成了一列字符,其最小循环节即为所求矩形块的宽;
将每列字符串当作一个字符,那么原矩形字符块就成了一行字符,其最小循环节即为所求矩形的长.
代码:
1 #include <iostream> 2 #include <stdio.h> 3 using namespace std; 4 5 const int MAXN = 1e5 + 10; 6 int nxt1[MAXN], nxt2[80]; 7 char str[MAXN][80]; 8 int n, m; 9 10 bool equal1(int x, int y){//判断两行字符串是否相等 11 for(int i = 0; i < m; i++){ 12 if(str[x][i] != str[y][i]) return false; 13 } 14 return true; 15 } 16 17 bool equal2(int x, int y){//判断两列字符串是否相等 18 for(int i = 0; i < n; i++){ 19 if(str[i][x] != str[i][y]) return false; 20 } 21 return true; 22 } 23 24 void get_nxt1(void){ //将每行字符串当作一个字符,求矩形字符块变成字符串后的nxt数组 25 int i = 0, j = -1; 26 nxt1[0] = -1; 27 while(i < n){ 28 if(j == -1 || equal1(i, j)) nxt1[++i] = ++j; 29 else j = nxt1[j]; 30 } 31 } 32 33 void get_nxt2(void){ //将每列字符串当作一个字符,求矩形字符块变成字符串后的nxt数组 34 int i = 0, j = -1; 35 nxt2[0] = -1; 36 while(i < m){ 37 if(j == -1 || equal2(i, j)) nxt2[++i] = ++j; 38 else j = nxt2[j]; 39 } 40 } 41 42 int main(void){ 43 scanf("%d%d", &n, &m); 44 for(int i = 0; i < n; i++){ 45 scanf("%s", str[i]); 46 } 47 get_nxt1(); 48 get_nxt2(); 49 int cnt1 = n - nxt1[n]; 50 int cnt2 = m - nxt2[m]; 51 printf("%d ", cnt1 * cnt2); 52 return 0; 53 }