poj1961 Period
我们考虑KMP算法中fail失配指针的意义。
对于一个模式串(Pattern),位置i对应的失配指针fail[i]是那个位置:
这个位置满足的条件是,子串[0, fail[i])是位置i(不含)的后缀,并且fail[i]是所有满足此条件的位置中最靠后(最接近i)的那个。
也就说当我们用模式串P匹配文本串T的时候,我们检查当前位置T[i]与P[j]是否匹配,
若匹配i,j指针各向前移动一位;
否则,利用模式子串[0, j)与文本子串i(不含)的后缀已经匹配的信息,保持i指针不变,j指针退到fail[j]位置再次尝试匹配。
退回的指针位置同样应该满足P的前缀与i(不含)后缀相匹配。
那么一个模式串fail指针蕴含着当前位置后缀与模式串前缀匹配的信息。
回到本题,考虑位置i(>0),若i位置是某个重复节(长度设为len)的终点,那么其失配指针必然指向(i - len)位置,
并且满足len | (i + 1) && str[i - len] == str[i]。
反之我们有满足此条件的必然是某个重复节的终点:
因为[0, fail[i]]可用字符串拼接表示:s1 + s2 + ... + sk + t,其中strlen(si) = len,
那么[len, i]必然是s2 +... + sk + t + t。
有s1 = s2 && s2 == s3 &&... && sk -1 = sk && sk = t。
可见该条件对于所求是等价的。
http://poj.org/problem?id=1961
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e6 + ;
char str[maxn];
int n;
int fail[maxn]; int main(){
//freopen("in.txt", "r", stdin);
int kase = ;
while(~scanf("%d", &n) && n){
char ch, *p = str;
while((ch = getchar()) != '\n') ch = getchar();
for(int i = ; i < n; i++) *(p++) = getchar();
fail[] = fail[] = ;
for(int i = ; i < n; i++){
//compute forward not backward
int j = fail[i];
while(j && str[j] != str[i]) j = fail[j];
fail[i + ] = str[j] == str[i] ? j + : ;
}
printf("Test case #%d\n", ++kase);
for(int i = ; i < n; i++){
int delta = i - fail[i];
if((i + ) % delta == && str[i] == str[fail[i]]){
printf("%d %d\n", i + , (i + ) / delta);
}
}
putchar('\n');
}
}
poj1961 Period的更多相关文章
- poj1961 Period kmp解决找字符串的最小循环节
/** 题目:poj1961 Period 链接:http://poj.org/problem?id=1961 题意:求从1到i这个前缀(2<=i<=N) ,如果有循环节(不能自身单独一个 ...
- POJ1961 Period && POJ2604 Power Strings 字符串循环节
两道题都是求循环节的...但是一道是学哈希时做的,另一道是学$KMP$时做的 POJ2604 用的哈希...枚举长度的因数作为循环节的长度,然后暴力算出所有循环节位置的哈希值,看看是否相等. #inc ...
- [POJ1961]Period (KMP)
题意 求字符串s的最小循环元长度和循环次数 思路 s[1~i]满足循环元要len能整除i并且s[len+1~i]=s[1~i-len] 代码 #include<cstdio> #inclu ...
- 【POJ1961 Period】【KMP】
题面 一个字符串的前缀是从第一个字符开始的连续若干个字符,例如"abaab"共有5个前缀,分别是a, ab, aba, abaa, abaab. 我们希望知道一个N位字符串S的前缀 ...
- 【POJ1961】period
[POJ1961]period 题目描述 如果一个字符串S是由一个字符串T重复K次构成的,则称T是S的循环元.使K出现最大的字符串T称为S的最小循环元,此时的K称为最大循环次数. 现在给定一个长度为N ...
- 0x15 字符串
KMP算法 next数组的求法 void calc_next() { next[]=; , j=; i<=n; ++i) { &&a[i]!=a[j+]) j=next[j]; ...
- 【题解】PERIOD - Period [POJ1961] [SP263]
[题解]PERIOD - Period [POJ1961] [SP263] 在进入这道题之前,我们需要了解 kmp 算法 不知道的童鞋可以去看一下Silent_EAG(一个可爱的女孩纸)的讲解. 关于 ...
- 「UVA1328」「POJ1961」 Period 解题报告
UVA1328 Period 其他链接:luogu UVA1328 POJ1961 For each prefix of a given string S with N characters (eac ...
- poj1961 & hdu1358 Period【KMP】
Period Time Limit: 3000MS Memory Limit: 30000K Total Submissions: 20436 Accepted: 9961 Descripti ...
随机推荐
- 解决Xamarin 生成时出现 “aapt.exe”已退出,代码为 1。错误问题
项目中添加的资源或项目文件的名称不能包含 空格 横线 特殊符号 或者 Android关键字 等
- Winform TreeView 节点拖动
private void treeView_ItemDrag(object sender, ItemDragEventArgs e) { TreeNode dragNode = e.Item as T ...
- [转]WEB开发者必备的7个JavaScript函数
我记得数年前,只要我们编写JavaScript,都必须用到几个常用的函数,比如,addEventListener 和 attachEvent,并不是为了很超前的技术和功能,只是一些基本的任务,原因是各 ...
- 是否可以继承String类?
是否可以继承String类? String类是final类故不可以继承
- Codeforces Beta Round #93 (Div. 1 Only) D. Fibonacci Sums
先考虑一个斐波那契数能分成其他斐波那契数的方案,假如f[i]表示第i个斐波那契数,那么只要对他进行拆分,f[i-1]这个数字必定会存在.知道这一点就可以进行递推了.先将数字分成最少项的斐波那契数之和, ...
- 刚刚学了循环,1到n的求和与阶乘
//求和 int a = Convert.ToInt32(Console.ReadLine()); int c = 0; for (int b = 0; b <= a; b++) { c = c ...
- delphi 读取excel 两种方法
http://www.cnblogs.com/ywangzi/archive/2012/09/27/2705894.html 两种方法,一是用ADO连接,问题是Excel文件内容要规则,二是用OLE打 ...
- 用VS2010编C#程序扫盲 2
0.正则表达式:http://www.runoob.com/csharp/csharp-regular-expressions.html 1.异常处理: try { // 引起异常的语句 } catc ...
- EXCEL 删除重复项并保留最大最小值
自定义排序 框选需要主次排序的区域 开始—排序和筛选—自定义排序 添加筛选条件 若要获取最小值则次要关键字选择升序 排序后的数据 删除重复项 数据—删除重复项 选择要删除的列 删除A列的重复项后,B列 ...
- 读 《JavaScript: The Good Parts》 有感
提炼出一门语言或技术的 Good Parts, 使用该子集去构造健壮稳固的应用. 我们总是倾向于去学习和使用所有的语言特性,好像凡是新的,凡是提供了的, 就有必要去使用: 这本书告诉我们, 要有选择性 ...