seekerhit 2019-11-05
题目链接:https://vjudge.net/problem/POJ-2185
题意:给定由大写字母组成的r×c矩阵,求最小子矩阵使得该子矩阵能组成这个大矩阵,但并不要求小矩阵刚好组成大矩阵,即边界部分可以空缺(见样例)。
思路:
把每一行视作一个字符,然后对r行求next数组,那么r-nex[r]即为以行为单元的最小循环节大小ans1。
把每一列视作一个字符,然后对c列求next数组,那么c-nex[c]即为以列为单元的最小循环节大小ans2。
最终答案即ans1*ans2。(子矩阵的面积)
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxr=10005;
const int maxc=80;
char s[maxr][maxc];
int ans1,ans2,r,c,nex1[maxr],nex2[maxc];
bool check1(int i,int j){
for(int k=0;k<c;++k)
if(s[i][k]!=s[j][k])
return false;
return true;
}
bool check2(int i,int j){
for(int k=0;k<r;++k)
if(s[k][i]!=s[k][j])
return false;
return true;
}
void get_next1(){
int j;
j=nex1[0]=-1;
for(int i=1;i<r;++i){
while(j>-1&&!check1(i,j+1)) j=nex1[j];
if(check1(i,j+1)) ++j;
nex1[i]=j;
}
}
void get_next2(){
int j;
j=nex2[0]=-1;
for(int i=1;i<c;++i){
while(j>-1&&!check2(i,j+1)) j=nex2[j];
if(check2(i,j+1)) ++j;
nex2[i]=j;
}
}
int main(){
scanf("%d%d",&r,&c);
for(int i=0;i<r;++i)
scanf("%s",s[i]);
get_next1();
get_next2();
ans1=r-(nex1[r-1]+1);
ans2=c-(nex2[c-1]+1);
printf("%d\n",ans1*ans2);
return 0;
}