[poj2185]Milking Grid_KMP
Milking Grid poj-2185
题目大意:给出一个字符矩阵,求最小覆盖矩阵(可以残余).
注释:$1\le R\le 10^5$,$1\le C \le 75$
想法:和bzoj1355不同的是,bz那题求的是最小覆盖子串。这题其实异曲同工。Discuss中讲的还是蛮清楚的,就是我们对于每一行单独求出Next数组,然后跑出每一行的所有的可能覆盖子串,然后用桶遍历出一个最小值即可。最后的乘积就是答案。
最后,附上丑陋的代码... ...
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int maxr=10002; const int maxc=80; char GetRead[maxr][maxc]; int row,col;//行和列 int rnext[maxr][maxc];//rnext[i]:对应第i行字符串的next函数 int cnext[maxr];//求纵向的next,每次比较的是整行 int rlen[maxr];//rlen[i]:第i行字符串的最小循环子串的长度 int cnt[maxc];//cnt[i]:统计各宽度出现的次数 int ans_for_col,ans_for_row;//最小覆盖矩阵的宽度和高度 void rgetNext(int r,char*str)// { int k=0; rnext[r][1]=0; for(int i=1;i<col;i++) { while(k&&str[k]!=str[i]) k=rnext[r][k]; if(str[k]==str[i]) k++; rnext[r][i+1]=k; } rlen[r]=col-rnext[r][col]; int i; for(i=rlen[r];i<=col;i+=rlen[r]) { cnt[i]++; } i-=rlen[r]; for(int j=i+1;j<=col;j++) { int x=0,y=j; while(str[x]==str[y]) { x++;y++; } if(y==col) cnt[j]++; } } void GetNext() { int k=0; cnext[1]=0; for(int i=1;i<row;i++) { while(k&& strcmp(GetRead[k],GetRead[i])!=0) k=cnext[k]; if(strcmp(GetRead[k],GetRead[i])==0) k++; cnext[i+1]=k; } ans_for_row=row-cnext[row]; } int main() { scanf("%d%d",&row,&col); for(int i=0;i<row;i++) { scanf("%s",GetRead[i]); } memset(cnt,0,sizeof(cnt)); for(int i=0;i<row;i++) { rgetNext(i,GetRead[i]); } GetNext(); for(int i=1;i<=col;i++) { if(cnt[i]==row) { ans_for_col=i; break; } } printf("%d\n",ans_for_col*ans_for_row); return 0; }
小结:挺好的一道题,有意义。网上大部分的题解全都是假的,很多并不极限的数据就能卡死。
| 欢迎来原网站坐坐! >原文链接<