最长回文子串

最长回文子串_第1张图片

一般求回文子串用的是Manacher算法,但是该算法只是简单判断回文,该题目中需要去除掉空格和标点,所以,自己用了动态规划(加剪枝,取出空号等)。

代码如下:

//最长回文子串  动态规划
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cctype>  //for tolower
#define MAXSIZE 5000
char str[MAXSIZE];//="Confuciuss say:Madam,I'm Adam.";
int d[MAXSIZE];  //表示状态,以i为末节点的回文长度
int begin[MAXSIZE];  //以i为末节点的回文序列的起始位置在哪

#define COMP(x)  ((str[x]<='z'&&str[x]>='a')||(str[x]<='Z'&&str[x]>='A'))

void printstr()  //输入字符串
{
    int i=0;
    char sh;
    printf("请输入样例:");
    scanf("%c",&sh);
    while(sh!='\n')
    {
        str[i++]=sh;
        scanf("%c",&sh);
    }
    str[i]=0;
}
int main()
{
    freopen("a.txt","r",stdin);
    printstr();
    int len=strlen(str);
    int i,j,k,num=1,flag=0;
    d[0]=COMP(0)?1:-1;
    begin[0]=d[0]?0:-1;
    for(i=1;i<len;i++)
    {
        if(!COMP(i))
        {
            d[i]=-1;
            begin[i]=-1;
            continue;
        }
        //给一个默认的初始化
        d[i]=1;
        begin[i]=i;
        j=i-1;
        while(d[j]==-1&&j>=0)
            j--;               //循环之后,确定j指定的位置一定是字母或者为-1
        if(j<0)
            continue;
        if(d[j]==1)
        {
            //case1:  a  a
            if(tolower(str[j])==tolower(str[i]))
            {
                d[i]=d[j]+1;
                begin[i]=j;
            }
            //  case2:  ac   a
            else if(j-1>=0)
            {
                k=j-1;
                while(d[k]==-1&&k>=0)
                    k--;
                if(k>=0&&tolower(str[k])==tolower(str[i]))
                {
                    d[i]=d[j]+2;
                    begin[i]=k;
                }
            }
        }
        else
        {
            //case3:  sssss  s
            char same=tolower(str[begin[j]]);
            for(k=begin[j]+1;k<=j;k++)
            {
                if(COMP(k))
                {
                    if(tolower(str[k])!=same)
                        break;
                }
            }
            if(k==j+1&&tolower(str[i])==same)
            {
                d[i]=d[j]+1;
                begin[i]=begin[j];
            }
            //case4:      sdad  s
            else
            {
                int temp=begin[j]-1;
                while(d[temp]==-1&&temp>=0)
                    temp--;
                if(temp<0) ;
                else if(tolower(str[temp])==tolower(str[i]))
                {
                    d[i]=d[j]+2;
                    begin[i]=temp;
                }
            }
        }
        if(d[i]>num)
        {
            num=d[i];
            flag=begin[i];
        }
        else if(d[i]==num&&begin[i]<flag)
            flag=begin[i];
    }
    printf("请输出样例:");
    for(i=flag,k=1;k<=num;i++)
    {
        if(COMP(i))
            k++;
        printf("%c",str[i]);
    }
    //printf("%d\n",num);
    return 0;
}








你可能感兴趣的:(最长回文子串)