zoukankan      html  css  js  c++  java
  • 最长的回文串——hdu3068

    http://acm.hdu.edu.cn/showproblem.php?pid=3068

    abcba 5

    aab 2

    在一个字符串里寻找一条最长的回文串

    比较直接的想法是枚举中心点 然后像两边扩散,但这样不仅要考虑最长子串的奇数偶数情况,而且时间复杂度会很高,因为会有比较多的重复计算

    分析 aaaab, abcba

    变成 #a#a#a#a#b# ,    #a#b#c#b#a#

    就都成了奇数子串

    现在再用一个数组P保存到该点的最长回文

    #a#a#a#a#b#

    12345432131

    if( mx > i )
    p[i] = min( p[2*id-i], mx-i ); 

    这一句减少了重复计算过程

    至于为什么要取小,考虑

    abcbabc

    #include<stdio.h>
    #include<string.h>
    
    char ss[400999];
    char ne[400999];
    int p[409999];
    int len;
    
    int min(int a,int b){
        return a>b?b:a;
    }
    
    void pre()
    {
        int i,n2;
        len=strlen(ss);
        n2=len*2;
        for(i=0;i<=n2;i++){
            p[i]=0;
        }
        ne[0]='#';
        for(i=0;i<len;i++){
            ne[2*i+1]=ss[i];
            ne[2*i+2]='#';
        }
        ne[2*len+1]='@';//end
    } 
    
    int cal(){
        int i,max=0;
        int id;
        int n=len*2;
        int mx = 0;
    
        for(i=1; i<n; i++)
        {
            if( mx > i )  
                p[i] = min( p[2*id-i], mx-i );        
            else
                p[i] = 1;
            for(; ne[i+p[i]] == ne[i-p[i]]; p[i]++)
                ;
            if( p[i] + i > mx )
            {
                mx = p[i] + i;
                id = i;
            }
        }
    
        for(i=1;i<n;i++){
            if(p[i]>max)max=p[i];
        }
    
        return max;
    }
    
    int main()
    {
        int n2,i,max=0,p;
        while(scanf("%s",ss)!=EOF){
            pre();max=cal();
            printf("%d
    ",max-1);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    SQL数据库inner join ,join,left join,full join(转)
    CSRF攻击(转)
    BZOJ1853: [Scoi2010]幸运数字
    BZOJ1935: [Shoi2007]Tree 园丁的烦恼
    BZOJ3289Mato的文件管理
    树状数组
    莫队算法
    如何在win上用Linux编c++
    Hash的应用
    关于指数循环节的证明
  • 原文地址:https://www.cnblogs.com/huhuuu/p/3298005.html
Copyright © 2011-2022 走看看