poj 2185(二维kmp)
题意:让你求一个最小的覆盖子矩阵。
分析:首先第一点是确定的:那就是这个子矩阵肯定位于左上角,然后按行考虑,求出每一行可能的重复子串的长度,然后取所有行都存在并且长度最短的长度最为最小子矩阵的宽,
最后按列队长度为宽的字符串进行一次kmp求出循环节的长度。
代码实现:
#include<cstdio> #include<cstring> #include<iostream> using namespace std; int n,m,windth,height; char str[10005][80]; int visited[80],next[10005]; void solve() { int i,j; for(i=0;i<n;i++) str[i][windth]='\0'; i=0;j=-1;next[0]=-1; while(i<n)//按列进行kmp求出最小子矩阵的高 { if(j==-1||strcmp(str[i],str[j])==0) { i++;j++; next[i]=j; } else j=next[j]; } height=n-next[n]; printf("%d\n",windth*height); } int main() { int i,j; int x,y; while(scanf("%d%d",&n,&m)!=EOF) { getchar(); memset(visited,0,sizeof(visited)); for(i=0;i<n;i++)//求出每一行都有的最小重复子串作为宽 { scanf("%s",str[i]); for(j=m;j>=1;j--) { x=0;y=0; for(;str[i][x]!='\0';x++,y++) { if(y==j) y=0; if(str[i][x]!=str[i][y]) break; } if(str[i][x]=='\0') visited[j]++; } } for(i=1;i<=m;i++) if(visited[i]==n) break; windth=i; solve(); } return 0; }
posted on 2013-09-16 20:32 后端bug开发工程师 阅读(302) 评论(0) 编辑 收藏 举报