• xdoj1012 字符串哈希


    xdoj1012 字符串哈希

    1012: 重复序列

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 149  解决: 15
    [提交][状态][讨论版]

    题目描述

    为了让密码变得更长,fpcsong在密码的末端增加了一些无意义内容。为了能够记住密码,增加的内容往往是重复序列。例如下列密码

    xduacm2015_mimayaochangchangchang

    的末端有一重复序列,即"chang"重复3次。现在,给你一个串s,请你确定一个串p和数x,使得p非空,x>1,px(指串p重复x次)为s的后缀。若有多个可能的解,输出x最大的解。若仍有多解,输出|p|(p的长度)最大的解。若无解,输出-1。

    输入

    多组数据,每组数据1行,包含一个串s。s中只有字母(大小写敏感),数字,下划线。|s|<=400000。

    输出

    对于每组数据,输出1行,若有解输出串p和整数x,用空格分割。若无解输出-1。

    样例输入

    xduacm2015_mimayaochangchangchang
    orzorzorzorz
    Orzorzorzorz
    orzorz_diaodiaodiaodiao
    we_orz_tencent_light_light
    ooooooooooops

    样例输出

    chang 3
    orz 4
    orz 3
    diao 4
    _light 2
    -1

    这道水题kmp可以做,后缀数组也可以做,字符串哈希也可以做。。。
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    
    using namespace std;
    
    typedef unsigned long long ull;
    const ull x=123LL;
    const int maxn=4000100;
    ull H[maxn],xp[maxn];
    ull Hash[maxn];
    char s[maxn];
    int n;
    struct Ans
    {
        int cnt,len;
        friend bool operator<(Ans A,Ans B)
        {
            if(A.cnt<B.cnt) return 1;
            if(A.cnt==B.cnt) return A.len<B.len;
            return 0;
        }
    };
    
    void Init()
    {
        H[n]=0;
        for(int i=n-1;i>=0;i--) H[i]=H[i+1]*x+(s[i]-'a');
        xp[0]=1;
        for(int i=1;i<=n;i++) xp[i]=xp[i-1]*x;
    }
    
    Ans solve(int L)
    {
        int i=n-L,j=n-2*L;
        if(j<0) return {-1,-1};
        Hash[i]=H[i]-H[i+L]*xp[L];
        Hash[j]=H[j]-H[j+L]*xp[L];
        int cnt=1;
        while(j>=0&&Hash[i]==Hash[j]){
            cnt++;
            j-=L;
            if(j>=0) Hash[j]=H[j]-H[j+L]*xp[L];
        }
        if(cnt==1) return {-1,-1};
        return {cnt,L};
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        while(cin>>s){
            n=strlen(s);
            Init();
            Ans ans={-1,-1};
            for(int i=1;i<=n;i++){
                Ans tmp=solve(i);
                if(ans<tmp) ans=tmp;
            }
            if(ans.cnt!=-1){
                for(int i=n-ans.len;i<n;i++) printf("%c",s[i]);
                printf(" ");
            }
            printf("%d",ans.cnt);
            puts("");
        }
        return 0;
    }
    View Code
    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    leetcode 39 Combination Sum
    C/C++ 单元测试 catch
    二叉树
    线性表
    POJ1002
    HDU4329
    hdu 4329
    java代码优化总结1
    Linux操作系统常用命令总结1
    java开发基础知识总结1
  • 原文地址:https://www.cnblogs.com/--560/p/4810067.html
Copyright © 2020-2023  润新知