Poj--2185(KMP,二维)
2014-12-13 01:00:47
思路:(吐槽下网上有些题解是的.....从百度文库打印的题解就错了orz...最后还是自己YY出的)
用KMP求出每行的最小重复字符串长度,求法就是总元素个数 - 最后一个字符的P[]值(与next数组不同概念,这里应该叫覆盖...)
比如:ABCAB,P[5]=2(假如下标从1开始),那么最小重复字符串长度为5-P[5] = 5-2 = 3,具体为什么这么做要想想P(覆盖数组)的定义(P的含义是最大周期包含长度,所以总长减去它自然就是最小周期长度,在题解POJ 2406中有讨论)
求的过程中得到每行最小重复字串长度的最大值a,同理能得到每列最小重复字串长度的最大值b,答案就是a×b
1 /************************************************************************* 2 > File Name: 2185.cpp 3 > Author: Natureal 4 > Mail: 564374850@qq.com 5 > Created Time: Fri 12 Dec 2014 04:29:13 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 27 int R,C,r,c; 28 char g[10010][80]; 29 30 int Solve1(int p){ 31 int P[80]; 32 P[0] = -1; 33 int j = -1; 34 for(int i = 1; i < C; ++i){ 35 while(j > -1 && g[p][j + 1] != g[p][i]) j = P[j]; 36 if(g[p][j + 1] == g[p][i]) j++; 37 P[i] = j; 38 } 39 return C - P[C - 1] - 1; 40 } 41 42 int Solve2(int p){ 43 int P[10010]; 44 P[0] = -1; 45 int j = -1; 46 for(int i = 1; i < R; ++i){ 47 while(j > -1 && g[j + 1][p] != g[i][p]) j = P[j]; 48 if(g[j + 1][p] == g[i][p]) j++; 49 P[i] = j; 50 } 51 return R - P[R - 1] - 1; 52 } 53 54 int main(){ 55 scanf("%d%d",&R,&C); 56 for(int i = 0; i < R; ++i){ 57 scanf("%s",g[i]); 58 } 59 r = c = 1; 60 for(int i = 0; i < R; ++i){ 61 r = max(r,Solve1(i)); 62 } 63 for(int i = 0; i < C; ++i){ 64 c = max(c,Solve2(i)); 65 } 66 printf("%d\n",r * c); 67 return 0; 68 }