zoukankan      html  css  js  c++  java
  • codeforces7D Palindrome Degree(manacher&dp或Hsh&dp)

    D. Palindrome Degree
    time limit per test
    1 second
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    String s of length n is called k-palindrome, if it is a palindrome itself, and its prefix and suffix of length  are(k - 1)-palindromes. By definition, any string (even empty) is 0-palindrome.

    Let's call the palindrome degree of string s such a maximum number k, for which s is k-palindrome. For example, "abaaba" has degree equals to 3.

    You are given a string. Your task is to find the sum of the palindrome degrees of all its prefixes.

    Input

    The first line of the input data contains a non-empty string, consisting of Latin letters and digits. The length of the string does not exceed 5·106. The string is case-sensitive.

    Output

    Output the only number — the sum of the polindrome degrees of all the string's prefixes.

    Sample test(s)
    input
    a2A
    
    output
    1
    input
    abacaba
    
    output
    6

    题意:

    定义回文串的度为length 即前半部分串的度或后半部分的度+1。先再给你一个字符串。

    要你求出他全部前缀度的和。

    思路:

    先用manacher求出以每一个位置为中心最大回文串的长度。

    dp[i]记录长度为i的前缀的度。那么dp[i+1]分奇偶用到前面的度即可了。

    具体见代码:

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    using namespace std;
    const int INF=0x3f3f3f3f;
    const int maxn=5110000;
    int p[maxn<<1],dp[maxn],len;
    char buf[maxn],st[maxn<<1];
    void init()
    {
        int i;
        len=strlen(buf);
        st[0]='$',st[1]='#';
        for(i=0;i<len;i++)
            st[2*i+2]=buf[i],st[2*i+3]='#';
        len=2*len+2;
    }
    void manacher()
    {
        int i,id,mx=0;
        for(i=1;i<len;i++)
        {
            p[i]=mx>i?

    min(mx-i,p[2*id-i]):1; while(st[i+p[i]]==st[i-p[i]]) p[i]++; if(i+p[i]>mx) mx=i+p[i],id=i; } } int main() { int i,ans,n; while(~scanf("%s",buf)) { ans=0,n=strlen(buf); init(); manacher(); ans=dp[0]=1; for(i=1;i<n;i++) { if(p[i+2]-1>=i+1)//推断该前缀是否回文。字符串从0開始。

    i+2为0到i在p数组对称中心无论回文串长度使是奇数还是偶数的。p[i]-1为最大回文长度 { if(i&1) dp[i]=dp[i/2]+1; else dp[i]=dp[i/2-1]+1; } ans+=dp[i]; } printf("%d ",ans); } return 0; }


    Hash的做法就比較简单了。

    具体见代码:

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    using namespace std;
    const int INF=0x3f3f3f3f;
    const int maxn=5110000;;
    unsigned long long H1[maxn],H2[maxn],xp[maxn],ha,hb,x=123;
    int dp[maxn],len;
    char buf[maxn],rbuf[maxn];
    void init()
    {
        int i;
        len=strlen(buf);
        H1[len]=H2[len]=0;
        xp[0]=1;
        for(i=len-1;i>=0;i--)
        {
            H1[i]=H1[i+1]*x+buf[i];
            H2[i]=H2[i+1]*x+rbuf[i];
            xp[len-i]=xp[len-i-1]*x;
        }
    }
    unsigned long long getHash(unsigned long long *HS,int s,int L)
    {
        return HS[s]-HS[s+L]*xp[L];
    }
    int main()
    {
        int i,ans;
        while(~scanf("%s",buf))
        {
            ans=0,len=strlen(buf);
            for(i=0;i<len;i++)
                rbuf[i]=buf[len-i-1];
            init();
            ans=dp[0]=1;
            for(i=1;i<len;i++)
            {
                ha=getHash(H1,0,i+1);
                hb=getHash(H2,len-i-1,i+1);
                if(ha==hb)
                {
                    if(i&1)
                        dp[i]=dp[i/2]+1;
                    else
                        dp[i]=dp[i/2-1]+1;
                }
                else
                    dp[i]=0;
                ans+=dp[i];
            }
            printf("%d
    ",ans);
        }
        return 0;
    }


  • 相关阅读:
    KindEditor简单的Demo使用
    动态从数据库读取菜单(ASP.NET版)
    完全卸载sql2005
    关于在xp(sp3 专业版)下安装sql2005开发版图解
    新手上路Tomcat 7.x和JDK的配置
    关于IE6幽灵字体
    【译】写个好的 CLI 程序
    【译】通过 Rust 学习解析器组合器 — Part 1
    【译】PHP 内核 — zval 基础结构
    【译】PHP 内核 — 字符串管理
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/6898857.html
Copyright © 2011-2022 走看看