【POJ2406】Power Strings 中文题意&题解&代码(C++)

Power Strings

Time Limit: 3000MS Memory Limit: 65536K

Description
Given two strings a and b we define a*b to be their concatenation. For example, if a = “abc” and b = “def” then a*b = “abcdef”. If we think of concatenation as multiplication, exponentiation by a non-negative integer is defined in the normal way: a^0 = “” (the empty string) and a^(n+1) = a*(a^n).

Input
Each test case is a line of input representing s, a string of printable characters. The length of s will be at least 1 and will not exceed 1 million characters. A line containing a period follows the last test case.

Output
For each s you should print the largest n such that s = a^n for some string a.

Sample Input

abcd
aaaa
ababab
.

Sample Output

1
4
3

Hint
This problem has huge input, use scanf instead of cin to avoid time limit exceed.


中文题意:题目输入若干个字符串,对于每个字符串求最短的循环节,并输出循环节的长度,若没有循环节则输出1,注意abcdab的循环节不为abcd,它没有循环节,因此若输入abcdab则输出1,输入一个 . 表示输入结束。


题解:
这道题十分巧妙的用到了kmp中nex数组的性质,它表示
s [ 0 … nex[i] ] == s [ i-nex[i]+1 … i ]
假如一个字符串 s 存在循环节时 t ,那么如图
【POJ2406】Power Strings 中文题意&题解&代码(C++)_第1张图片
因为nex的定义是最长的前缀等于后缀,所以如果存在循环节时,len-nex[len]就一定是最短的那个循环节的长度,当len%(len-nex[len])==0时,说明存在循环节,否则就不存在,证明如下:
【POJ2406】Power Strings 中文题意&题解&代码(C++)_第2张图片
假如 nex[len] 位置 x 时
当 len%(len-nex[len])==0 时,那么 len%(len-nex[len]-a.len-b.len)==0(因为a.len=b.len=len-nex[len]),所以中间重叠的部分也可以被分为长度为 len-nex[len] 的字符串,此时a1==b2 b2==b3 a3==b4
又因为 a==b可以推出 a1==b1==a2==a3==a4==b2==b3==b4。
所以len-nex[len]为循环节的长度。
假若 len%(len-nex[len])!=0 ,由以上可以看出中间重叠的部分不能正好分成长度为 len-nex[len] ,因此也不可能出现循环节。


代码:

#include
#include
#include
#include
using namespace std;
int len,nex[1000005];
char s[1000005];
void getnex()
{
    int j=-1;
    for (int i=0;iwhile(j!=-1 && s[j+1]!=s[i]) j=nex[j];
        if (s[j+1]==s[i] && i!=0) j++;
        nex[i]=j;
    }
}
int main()
{
    while(scanf("%s",s))
    {
        if (s[0]=='.')
        break;
        len=strlen(s);
        getnex();
        if (len%(len-nex[len-1]-1)==0&&len!=nex[len-1]+1)
        printf("%d\n",len/(len-nex[len-1]-1));
        else 
        printf("1\n");
    }
}

你可能感兴趣的:(oi之路)