我们考虑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. WebService之Axis2 后续(6)~(10)目录

    WebService大讲堂之Axis2(6):跨服务会话(Session)管理 WebService大讲堂之Axis2(7):将Spring的装配JavaBean发布成WebService WebSe ...

  2. [翻译]java nio 概述

    原文地址:http://tutorials.jenkov.com/java-nio/overview.html java NIO 包含一下核心内容: Channels Buffers Selector ...

  3. 用 mCustomScrollbar 滚动条插件实现滚动更新添加数据

    在公司的一个小项目中,需要从后台获取一大堆数据,为了用户体验的考虑,需要分部加载,然后就在网上找了很多的滚动插件,终于找到一个合适的.mCustomScrollbar插件地址 点击这里 它有各种各样的 ...

  4. java mock

    一篇文章: 5分钟了解Mockito 一.什么是mock测试,什么是mock对象? 先来看看下面这个示例: 从上图可以看出如果我们要对A进行测试,那么就要先把整个依赖树构建出来,也就是BCDE的实例. ...

  5. composer很慢修改镜像

    有两种方式启用本镜像服务: 系统全局配置: 即将配置信息添加到 Composer 的全局配置文件 config.json 中.见“例1” 单个项目配置: 将配置信息添加到某个项目的 composer. ...

  6. c++ DISALLOW_COPY_AND_ASSIGN

    Google C++编程规范 – 第三十二条 -<拷贝构造函数> [规范] 仅在确认需要的时候,才定义拷贝构造函数和赋值运算符:否则,请使用DISALLOW_COPY_AND_ASSIGN ...

  7. Hibernate Annotation笔记

    (1)简介:在过去几年里,Hibernate不断发展,几乎成为Java数据库持久性的事实标准.它非常强大.灵活,而且具备了优异的性能.在本文中,我们将了解如何使用Java 5 注释来简化Hiberna ...

  8. Aptana Studio3开发Python和Ruby(最佳工具)

    即从: http://d1iwq2e2xrohf.cloudfront.net/tools/studio/standalone/3.3.1.201212171919/win/Aptana_Studio ...

  9. Android 测试Service的生命周期

    package com.example.myapp4; import android.support.v7.app.ActionBarActivity; import android.content. ...

  10. [tp3.2.1]大D构建模型

    使用大(写字母)D方法: 如果,在默认到Home模块下面找不到UserModel模块,那么就会到Common模块下去找. 而如果此时在Common模块下还是找不到UserModel,那就会调用Mode ...