我们考虑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. openSuSE DNS SERVER CONFIG

    system:openSuSE 12.3(much better and frendly than the 12.1 in network config)1,network config,attent ...

  2. UltraEdit常用配置&搭建Java/C开发环境

    一:个人使用UE期间总结了以下经常使用的配置 1.手动配置语法高亮 [高级]->[配置]->[编辑器显示]->[语法高亮]->[词语列表的完整路径]->[浏览]找到安装目 ...

  3. HTML基础-- 标签、表格

    <html>    --开始标签 <head> 网页上的控制信息 <title>页面标题</title> </head> <body& ...

  4. ORACLE数据库创建用户名和表空间

    [sql] /*第1步:登录  */  以sys/sys超级用户登录pl/sql      /*第2步:创建临时表空间  */  create temporary tablespace user_te ...

  5. SQL 2008 数据库只读 修改

        先对数据库分离 数据库鼠标右键->任务->分离   将UsersDB.mdf UsersDB_log.LDF文件 属性->安全->编辑   两个文件的都要更改权限   ...

  6. 转:JAVA强制类型转换

    object对象转换为String的一些总结 ----------------------------------------------------------------------------- ...

  7. 【Origin】羡旁人

    -道行至一桥畔,微风轻抚,观河岸杨柳柳枝空舞,看满路车辆畅行无阻,虽羡,然各有归途. 小河岸,棵棵杨柳,柳枝随风摆; 大路上,盏盏绿灯,一路往北开. 横批: 可惜不是我 -作于二零一六年三月二十二日

  8. [原创]java WEB学习笔记65:Struts2 学习之路--Struts的CRUD操作( 查看 / 删除/ 添加) ModelDriven拦截器 paramter 拦截器

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  9. 利用Hudson持续集成来执行Android自动化测试(转)

    当你套用Athrun.Robotium等框架,针对自己的项目写完了一堆自动化测试脚本后,在Eclipse之外怎么让它们可以持续性地跑起来并展现报告呢? 据我了解,方便的方法大致有两个:其一,利用Hud ...

  10. Android设计模式---观察者模式小demo(一)

    1,今天刚好看到了设计模式这一块来,而观察者模式是我一直想总结的,先来看看观察者模式的简单的定义吧 "当一个对象改变时,他的所有依赖者都会受到通知,并自动更新." 一般我们项目中就 ...