我们考虑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的更多相关文章

  1. poj1961 Period kmp解决找字符串的最小循环节

    /** 题目:poj1961 Period 链接:http://poj.org/problem?id=1961 题意:求从1到i这个前缀(2<=i<=N) ,如果有循环节(不能自身单独一个 ...

  2. POJ1961 Period && POJ2604 Power Strings 字符串循环节

    两道题都是求循环节的...但是一道是学哈希时做的,另一道是学$KMP$时做的 POJ2604 用的哈希...枚举长度的因数作为循环节的长度,然后暴力算出所有循环节位置的哈希值,看看是否相等. #inc ...

  3. [POJ1961]Period (KMP)

    题意 求字符串s的最小循环元长度和循环次数 思路 s[1~i]满足循环元要len能整除i并且s[len+1~i]=s[1~i-len] 代码 #include<cstdio> #inclu ...

  4. 【POJ1961 Period】【KMP】

    题面 一个字符串的前缀是从第一个字符开始的连续若干个字符,例如"abaab"共有5个前缀,分别是a, ab, aba, abaa, abaab. 我们希望知道一个N位字符串S的前缀 ...

  5. 【POJ1961】period

    [POJ1961]period 题目描述 如果一个字符串S是由一个字符串T重复K次构成的,则称T是S的循环元.使K出现最大的字符串T称为S的最小循环元,此时的K称为最大循环次数. 现在给定一个长度为N ...

  6. 0x15 字符串

    KMP算法 next数组的求法 void calc_next() { next[]=; , j=; i<=n; ++i) { &&a[i]!=a[j+]) j=next[j]; ...

  7. 【题解】PERIOD - Period [POJ1961] [SP263]

    [题解]PERIOD - Period [POJ1961] [SP263] 在进入这道题之前,我们需要了解 kmp 算法 不知道的童鞋可以去看一下Silent_EAG(一个可爱的女孩纸)的讲解. 关于 ...

  8. 「UVA1328」「POJ1961」 Period 解题报告

    UVA1328 Period 其他链接:luogu UVA1328 POJ1961 For each prefix of a given string S with N characters (eac ...

  9. poj1961 & hdu1358 Period【KMP】

    Period Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 20436   Accepted: 9961 Descripti ...

随机推荐

  1. 解决Xamarin 生成时出现 “aapt.exe”已退出,代码为 1。错误问题

    项目中添加的资源或项目文件的名称不能包含 空格 横线 特殊符号 或者 Android关键字 等

  2. Winform TreeView 节点拖动

    private void treeView_ItemDrag(object sender, ItemDragEventArgs e) { TreeNode dragNode = e.Item as T ...

  3. [转]WEB开发者必备的7个JavaScript函数

    我记得数年前,只要我们编写JavaScript,都必须用到几个常用的函数,比如,addEventListener 和 attachEvent,并不是为了很超前的技术和功能,只是一些基本的任务,原因是各 ...

  4. 是否可以继承String类?

    是否可以继承String类? String类是final类故不可以继承

  5. Codeforces Beta Round #93 (Div. 1 Only) D. Fibonacci Sums

    先考虑一个斐波那契数能分成其他斐波那契数的方案,假如f[i]表示第i个斐波那契数,那么只要对他进行拆分,f[i-1]这个数字必定会存在.知道这一点就可以进行递推了.先将数字分成最少项的斐波那契数之和, ...

  6. 刚刚学了循环,1到n的求和与阶乘

    //求和 int a = Convert.ToInt32(Console.ReadLine()); int c = 0; for (int b = 0; b <= a; b++) { c = c ...

  7. delphi 读取excel 两种方法

    http://www.cnblogs.com/ywangzi/archive/2012/09/27/2705894.html 两种方法,一是用ADO连接,问题是Excel文件内容要规则,二是用OLE打 ...

  8. 用VS2010编C#程序扫盲 2

    0.正则表达式:http://www.runoob.com/csharp/csharp-regular-expressions.html 1.异常处理: try { // 引起异常的语句 } catc ...

  9. EXCEL 删除重复项并保留最大最小值

    自定义排序 框选需要主次排序的区域 开始—排序和筛选—自定义排序 添加筛选条件 若要获取最小值则次要关键字选择升序 排序后的数据 删除重复项 数据—删除重复项 选择要删除的列 删除A列的重复项后,B列 ...

  10. 读 《JavaScript: The Good Parts》 有感

    提炼出一门语言或技术的 Good Parts, 使用该子集去构造健壮稳固的应用. 我们总是倾向于去学习和使用所有的语言特性,好像凡是新的,凡是提供了的, 就有必要去使用: 这本书告诉我们, 要有选择性 ...