GHOJ 818 Power Strings

题目描述

  给定若干个长度小于等于10^6的字符串,询问每个字符串最多由多少个相同的子串重复连接而成。如:ababab,最多由3个ab连接而成。

 

输入输出格式

输入格式

  若干行,每行一个字符串。

  当读入到“.”时结束程序。

输出格式

  若干行,为对应的答案。

输入输出样例

输入样例

abcd

aaaa

ababab

.

输出样例

1

4

3

题解

  这道题可以用字符串hash或kmp来做。

  主要就是要将这道题转换成求最长前缀满足同为后缀。

  假设在s[1...n]中,s[1...i]为前缀且s[n-i+1...n]为后缀,那么当i>=n-i+1时,s[1...n-i]=s[n-i+1...n-i+1+n-i]=...=s[i+1][n],继续推下去,可以证得当i|n时,i就是其中相同子串中的一个,求出最长的i即可得出结果。

#include <cstdio>
#include <cstring>

#define MAX_N 1000000

using namespace std;

int n;
const unsigned long long b = 128;
char s[MAX_N | 1];
unsigned long long p[MAX_N | 1], h[MAX_N | 1];

int main()
{
    p[0] = 1;
    for(register int i = 1; i < MAX_N; ++i)
    {
        p[i] = p[i - 1] * b;
    }
    int op;
    while(scanf("%s", s))
    {
        op = 0;
        n = strlen(s);
        if(n == 1 && s[0] == '.') break;
        h[0] = s[0];
        for(register int i = 1; i < n; ++i)
        {
            h[i] = h[i - 1] * b + s[i];
        }
        for(register int i = 1; i < n; ++i)
        {
            if(h[n - i - 1] == h[n - 1] - h[i - 1] * p[n - i])
            {
                if(n % i) continue;
                printf("%d
", n / i);
                op = 1;
                break;
            }
        }
        if(!op) printf("1
");
    }
    return 0;
}
参考程序(字符串hash)
#include <cstdio>
#include <cstring>

#define MAX_N 1000000

using namespace std;

int n;
char a[MAX_N | 1];
int p[MAX_N | 1];

int main()
{
    while(scanf("%s", a) && (a[0] ^ '.'))
    {
        n = strlen(a);
        p[0] = -1;
        for(register int i = 0, j = -1; i + 1 < n; ++i)
        {
            while(j >= 0 && (a[i + 1] ^ a[j + 1])) j = p[j];
            if(a[i + 1] == a[j + 1]) ++j;
            p[i + 1] = j;
        }
        if(n % (n - p[n - 1] - 1)) printf("1
");
        else printf("%d
", n / (n - p[n - 1] - 1));
    }
    return 0;
}
参考程序(kmp)
原文地址:https://www.cnblogs.com/kcn999/p/10290608.html