zoukankan      html  css  js  c++  java
  • 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)
  • 相关阅读:
    linux常用命令(二)文件上传下载及软件安装
    linux常用命令(一)linux开关机、重启以及文本界面与图形界面互换
    HTTP协议(一)基本概念、HTTP方法、HTTP状态码
    Martin Fowler 分层测试概念博文分享
    网络路由分析
    nginx 常见错误释义
    java解决共享资源竞争
    python操作excel及json
    一个简单的用python 实现系统登录的http接口服务实例
    Redis持久化之RDB&&AOF的区别
  • 原文地址:https://www.cnblogs.com/kcn999/p/10290608.html
Copyright © 2011-2022 走看看