POJ-2406Power Strings-KMP+定理

Power Strings

题意:给一个字符串S长度不超过10^6,求最大的n使得S由n个相同的字符串a连接而成,如:"ababab"则由n=3个"ab"连接而成,"aaaa"由n=4个"a"连接而成,"abcd"则由n=1个"abcd"连接而成。

定理:假设S的长度为len,则S存在循环子串,当且仅当,len可以被len - next[len]整除,最短循环子串为S[len - next[len]]

例子证明:
设S=q1q2q3q4q5q6q7q8,并设next[8] = 6,此时str = S[len - next[len]] = q1q2,由字符串特征向量next的定义可知,q1q2q3q4q5q= q3q4q5q6q7q8,即有q1q2=q3q4,q3q4=q5q6,q5q6=q7q8,即q1q2为循环子串,且易知为最短循环子串。由以上过程可知,若len可以被len - next[len]整除,则S存在循环子串,否则不存在。

解法:利用KMP算法,求字符串的特征向量next,若len可以被len - next[len]整除,则最大循环次数n为len/(len - next[len]),否则为1。

我的ac代码:

#include <cstring>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>

using namespace std;
string str;
int len,nx[1000000+10];

void getnext()
{
    int j = 0,k = -1;
    nx[0] = -1;
    while(j<len)
    {
        if(k==-1||str[j]==str[k])
        {
            nx[++j]=++k;
        }else
        {
            k=nx[k];
        }
    }
}

int main(){
    while(cin>>str)
    {
        if(str[0]=='.')break;
        len = str.length();
        getnext();
        if(len % (len-nx[len]) == 0)
        {
            cout<<len/(len-nx[len])<<endl;
        }
        else cout<<1<<endl;
    }
    return 0;
}
skr
原文地址:https://www.cnblogs.com/ckxkexing/p/8424464.html