kmp求字符串最小周期

总时间限制: 
3000ms 
内存限制: 
65536kB
描述

给定两个字符串ab,我们定义a*b为他们的连接。例如,如果a=”abc” b=”def” a*b=”abcdef” 如果我们将连接考虑成乘法,一个非负整数的乘方将用一种通常的方式定义:a^0=””(空字符串)a^(n+1)=a*(a^n)

输入
每一个测试样例是一行可打印的字符作为输入,用s表示。s的长度至少为1,且不会超过一百万。最后的测试样例后面将是一个点号作为一行。
输出
对于每一个s,你应该打印最大的n,使得存在一个a,让s=a^n
样例输入
abcd
aaaa
ababab
.
样例输出
1
4
3
提示
本问题输入量很大,请用scanf代替cin,从而避免超时。
来源
Waterloo local 2002.07.01
//poj 2406 power string 
#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;

#define maxlen 1000000

char str[maxlen+1];
int next[maxlen+1];

void getNext(int len)
{
    int i = 0, j = -1;
    next[i] = j;
    while(i < len){
        if(j == -1 || str[i] == str[j]){
            i++, j++;
            next[i] = j;
        }
        else
            j = next[j];
    }
}

int main()
{
    int len = 0;
    while(scanf("%s", str)){
        if(str[0] == '.') break;

        int len = strlen(str);
        getNext(len);
        if(len%(len-next[len]) || next[len] == 0)   //如果len整除(len-next[len]),则最小周期为len-next[len]
            cout << 1 << endl;
        else
            cout << len/(len-next[len]) << endl;

    }
    return 0;
}


前缀中的周期

总时间限制: 
3000ms 
内存限制: 
65536kB
描述
一个字符串的前缀是从第一个字符开始的连续若干个字符,例如”
abaab”共有5个前缀,分别是a, ab, aba, abaa,  
abaab。

我们希望知道一个N位字符串S的前缀是否具有循环节。换言之,对于每一个从头开始的长度为 i (i 大于1)的前缀,是否由重复出现的子串A组成,即 AAA…A (A重复出现K次,K 大于 1)。如果存在,请找出最短的循环节对应的K值(也就是这个前缀串的所有可能重复节中,最大的K值)。

输入
输入包括多组测试数据。每组测试数据包括两行。

第一行包括字符串S的长度N(2 <= N <= 1 000 000)。

第二行包括字符串S。

输入数据以只包括一个0的行作为结尾。

输出
对于每组测试数据,第一行输出 “Test case #“ 和测试数据的编号。

接下来的每一行,输出前缀长度i和重复测数K,中间用一个空格隔开。前缀长度需要升序排列。

在每组测试数据的最后输出一个空行。

样例输入
3
aaa
12
aabaabaabaab
0
样例输出
Test case #1
2 2
3 3

Test case #2
2 2
6 2
9 3
12 4
#include <iostream>

using namespace std;

#define maxlen 1000000

char str[maxlen+1];
int next[maxlen];

void getNext(int n)
{
    int i = 0, j = -1;
    next[i] = j;
    while(i < n){
        if(j == -1 || str[i] == str[j]){
            i++;
            j++;
            next[i] = j;
        }
        else
            j = next[j];
    }
}

int main()
{
    int n, cases = 1;
    while(cin >> n){
    if(!n) break;

    cin >> str;
    getNext(n);

    cout << "Test case #" << cases++ << endl;
    for(int i = 1; i < n; i++){
        if((i+1)%(i+1-next[i+1]) == 0 && next[i+1])
            cout << i+1 << " "  << (i+1)/(i+1-next[i+1]) << endl;
    }
    cout << endl;
  }
}



    原文作者:KMP算法
    原文地址: https://blog.csdn.net/htt_h/article/details/39760793
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞