POJ 2185 Milking Grid(KMP最小循环节)
http://poj.org/problem?id=2185
题意:
给出一个r行c列的字符矩阵,求最小的覆盖矩阵可以将原矩阵覆盖,覆盖矩阵不必全用完。
思路:
我对于字符串的最小循环节是这么理解的:
如果next[12]=5,那么前5个前缀字符和后5个后缀字符是一样,但是此时还需要加上中间的2个,所以循环节为7。
如果next[12]=7,那么中间2个既出现在了前缀里,也出现在了后缀里,所以中间的2个字符等于开头的两个字符。此时循环节为5。
这样的话,字符串的最小循环节就是 len - next[len] 。
那么这道题的话:
对每一行求最小循环节,并对所有行求最小公倍数。
对每一列求最小循环节,并对所有列求最小公倍数。
相乘得最小面积。
注意:
如果此时的最小公倍数大于了行或列,可以直接等于行或列并退出了。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<stack> 7 #include<queue> 8 #include<cmath> 9 using namespace std; 10 11 const int maxn=100+5; 12 13 int r,c; 14 char str[10005][80]; 15 int next[10005]; 16 17 int gcd(int a,int b) 18 { 19 return b==0?a:gcd(b,a%b); 20 } 21 22 void get_nextrow(int r) 23 { 24 int i=-1,j=0; 25 next[0]=-1; 26 while(j<c) 27 { 28 if(i==-1 || str[r][i]==str[r][j]) 29 next[++j]=++i; 30 else 31 i=next[i]; 32 } 33 } 34 35 void get_nextcol(int c) 36 { 37 int i=-1,j=0; 38 next[0]=-1; 39 while(j<r) 40 { 41 if(i==-1 || str[i][c]==str[j][c]) 42 next[++j]=++i; 43 else 44 i=next[i]; 45 } 46 } 47 48 int main() 49 { 50 //freopen("D:\\input.txt","r",stdin); 51 scanf("%d%d",&r,&c); 52 for(int i=0;i<r;i++) 53 scanf("%s",&str[i]); 54 55 int row=1; 56 for(int i=0;i<r;i++) 57 { 58 get_nextrow(i); 59 row=row*(c-next[c])/gcd(row,c-next[c]); 60 if(row>=c) 61 { 62 row=c; 63 break; 64 } 65 } 66 67 int col=1; 68 for(int i=0;i<c;i++) 69 { 70 get_nextcol(i); 71 col=col*(r-next[r])/gcd(col,r-next[r]); 72 { 73 if(col>=r) 74 { 75 col=r; 76 break; 77 } 78 } 79 } 80 printf("%d\n",row*col); 81 }
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步