uvalive3026 Period (KMP+结论)
2014-08-12 21:30
483 查看
题目链接:http://vjudge.net/problem/viewProblem.action?id=29342
题目大意:给定字符串,找到每个前缀的最大循环节的个数。
首先当然是kmp预处理,接下来的问题是 怎么找循环节?
用反证法可以证明,如果f[i]~i之间的字符串能构成循环节,则该字符串就是i前缀对应的循环节,否则循环节不存在。
对每个前缀找到尾指针对应的失陪位置后,不需要按失陪指针继续往前寻找了(否则超时)。
只用判断上个位置到尾部的字符串是否是循环节(长度是否有整除关系),即知循环节个数。
代码奉上:
证明没有仔细说,不明白的欢迎留言讨论
题目大意:给定字符串,找到每个前缀的最大循环节的个数。
首先当然是kmp预处理,接下来的问题是 怎么找循环节?
用反证法可以证明,如果f[i]~i之间的字符串能构成循环节,则该字符串就是i前缀对应的循环节,否则循环节不存在。
对每个前缀找到尾指针对应的失陪位置后,不需要按失陪指针继续往前寻找了(否则超时)。
只用判断上个位置到尾部的字符串是否是循环节(长度是否有整除关系),即知循环节个数。
代码奉上:
#include <stdio.h> #include <algorithm> #include <stdlib.h> #include <cstring> int f[1000010]; char p[1000010]; void deal(int l){ f[0]=-1; int i=0,k=-1; while(i<l){ if(k==-1 || p[k]==p[i])f[++i]=++k; else k=f[k]; } //for(i=0;i<l;i++)printf("%d: %d\n",i,f[i]); } int main(){ int n,cs=1; while(scanf("%d",&n) && n){ scanf("%s",p); deal(n); printf("Test case #%d\n",cs++); int i,k; for(i=1;i<=n;i++){ if(f[i]==0 || i%(i-f[i]))continue; k=i/(i-f[i]); if(k>1)printf("%d %d\n",i,k); } printf("\n"); } return 0; }
证明没有仔细说,不明白的欢迎留言讨论
相关文章推荐
- uvaLive 3026 - Period 水KMP循环结
- UVALive 3026 Period KMP 失配函数处理周期的问题
- UVALive 3026 Period(KMP裸)
- UVALive 3026 (LA 3026) Period KMP求字符串周期
- uvalive 3026 Period KMP(失配函数)
- UVALive 3026 Period ( kmp 求前缀最小循环节)
- Uvalive - 3026 Period (kmp求字符串的最小循环节+最大重复次数)
- UVALive - 3026 - Period (KMP)
- Period UVALive - 3026(KMP)
- UVALive 3026 Period (KMP上的dp,学习ac自动机的前奏)
- Period UVALive - 3026(KMP)
- UVALive - 3026:Period
- 【暑假】[实用数据结构]UVAlive 3026 Period
- uvalive 3026(kmp)
- UVALive 3026 Period (KMP算法简介)
- UVALive - 3026 Period
- KMP UVALive326 Period
- 【暑假】[实用数据结构]UVAlive 3026 Period
- UVALive 3026 period(周期) kmp算法的应用
- uva 1328 && Live Archive 3026 Period