kmp求字符串最小周期

来源:互联网 发布:守望先锋排位分数算法 编辑:程序博客网 时间:2024/05/19 23:17

总时间限制: 
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
样例输入
abcdaaaaababab.
样例输出
143
提示
本问题输入量很大,请用scanf代替cin,从而避免超时。
来源
Waterloo local 2002.07.01
//poj 2406 power string 
#include <iostream>#include <cstdio>#include <string.h>using namespace std;#define maxlen 1000000char 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,中间用一个空格隔开。前缀长度需要升序排列。
在每组测试数据的最后输出一个空行。
样例输入
3aaa12aabaabaabaab0
样例输出
Test case #12 23 3Test case #22 26 29 312 4

#include <iostream>using namespace std;#define maxlen 1000000char 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;  }}








0 0
原创粉丝点击