zoukankan      html  css  js  c++  java
  • 最大回文子串

    题目:输入一个字符串,输出该字符串中对称的子字符串的最大长度。
    比如输入字符串“google”,由于该字符串里最长的对称子字符串是“goog”,因此输出4。


    主要是参考了一下两篇文章:

    http://blog.csdn.net/qitian0008/article/details/8042558

    http://www.cnblogs.com/eric-blog/archive/2012/05/03/2481510.html

    其中常规的方法,就是用一个i从左到右进行遍历,当i指向某个值的时候,以i为中心,逐个比较左右两个的字符是否相等。

    这样就可以找到一个回文,以及他的长度。

    但是,这样做的时候,是有重复计算的过程的。比如你找到一个回文,这个回文是左右对称的,那么你在计算右边范围内的某个字符,计算这个字符为中心的回文长度的时候,就可以利用他对称的左边的字符的回文长度,这样就可以实现简化,也就那个O(n)算法的思想。

    但是计算回文的时候,有一个小问题,就是回文是奇数还是偶数,有个避免这种判断的方法就是在每个字幕中间插入#号,这样所有的都是奇数了。

    好了,所有的问题都解决了,看代码吧。

    #include <iostream>
    using namespace std;
    
    int getMaxHuiWenChar1(char *p,int len)  
    {  
        int nLen=2*len+3;  
        char *str =new char[nLen];  
        int i=0;  
        int max=0;  
        int j=0,x,y;  
        str[0]='$';  
        str[1]='#';  
        for(;i<len;i++)
        {  
            str[i*2+2]=p[i];  
            str[i*2+3]='#';  
        }  
        str[nLen-1]=0;  
    
        for(i=0;i<nLen;i++)  
        {  
            cout<<str[i];  
        }  
        cout<<endl;  
    
        for(i=1;i<nLen;i++)  
        {  
            for(int j=0; i-j>0&&i+j<nLen; j++)
            {
                if(str[i-j]!=str[i+j])
                    break;
                else
                {
                    if(max<j)
                    {
                        max=j;  
                        x=i-j;  
                        y=i+j;  
                    }
                }
            }
        }  
    
        for(int k=x+1;k<=y-1;k+=2)//打印出回文  
        {  
            cout<<str[k];  
        }  
        return max;  
    }  
    int min(int a, int b)
    {
        return a<b?a:b;
    }
    int getMaxHuiWenChar2(char *s,int len)  
    {  
        int nLen=2*len+3;  
        char *str =new char[nLen];  
        int i=0;  
        int max=0;  
        str[0]='$';  
        str[1]='#';  
        for(;i<len;i++)  
        {  
            str[i*2+2]=s[i];  
            str[i*2+3]='#';  
        }  
        str[nLen-1]=0;  
        int *p=new int[nLen];//定义一个用于标记的int数组  
    
        for(i=1;i<nLen;i++)  
        {  
            cout<<str[i];  
            p[i]=0;  
        }  
        cout<<endl;  
    
        int id=0;  
        for(i=1; i<nLen; i++)  
        {  
            if( max > i )  
                p[i] = min( p[2*id-i], p[id]+id-i  );
            else  
                p[i] = 1;  
            for(; str[i+p[i]] == str[i-p[i]]; p[i]++)  
                NULL;  
            if( p[i] + i > max )  
            {  
                max = p[i] + i;  
                id = i;  
            }  
        }  
    
        int mx=0;  
        for(i=1;i<nLen;i++)  
        {  
            if(mx<p[i]-1)  
                mx=p[i]-1;  
        }  
        return mx;  
    }  
    
    int main(int argc, char* argv[])  
    {  
        char *p="abcgooglrcabac";  
        int len=strlen(p);  
        int max=getMaxHuiWenChar2(p,len);  
        cout<<endl;  
        cout<<max<<endl;  
        return 0;  
    }  

     

     

  • 相关阅读:
    8.10
    今日头条笔试题 1~n的每个数,按字典序排完序后,第m个数是什么?
    Gym 100500B Conference Room(最小表示法,哈希)
    CodeForces 438D The Child and Sequence(线段树)
    UVALIVE 6905 Two Yachts(最小费用最大流)
    Gym Conference Room (最小表示法,哈希)
    hdu 2389 Rain on your Parade(二分图HK算法)
    Codeforces Fox And Dinner(最大流)
    zoj 3367 Counterfeit Money(dp)
    ZOJ3370. Radio Waves(2-sat)
  • 原文地址:https://www.cnblogs.com/cyttina/p/2744015.html
Copyright © 2011-2022 走看看