最长回文子串求解

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 的最大长度为1000。

示例:

babad

输出:

bab(注意aba也是有效答案)

思路:

1、可以枚举出所有的子串,然后每次都判断该子串是否是回文,若是回文便更新最大长度,并且记录子串的开始位置和结束位置。

2、可以从第一个字符为中心向两边检查,若以k为中心 ,那么i往K的左边检测,j往右边检测。若s[i]==s[j]那么说明从i-j的子串为回文,接下来只需要判断s[i-1],s[j+1]是否相同,若相同则也是子串,并更新长度,并更新最长子串的开始位置和结束位置,直到当条件不满足s[i]==s[j]的时候,将中心点k往后移动。


方法一(暴力求解)
class Solution {
public:
    bool judge(string &s, int star, int end)//判断子串是否是回文,分为奇偶两种情况
    {
        int median;
        int length = end-star;;
        if(length%2==0)
        {
            median = length/2;
            for(int i=star; i<=star-1+median; i++)
            {
                if(s[i]==s[--end])
                {
                    continue;
                }
                else
                {
                    return false;
                }
            }
            return true;
        }
        if(length%2!=0)
        {
            median = length/2;
            for(int i=star; i<star+median; i++)
            {
                if(s[i]==s[--end])
                {
                    continue;
                }
                else
                {
                    return false;
                }
            }
            return true;
        }
    }
    string longestPalindrome(string s) {
        int len = s.size();
        string st;
        int max = 0;
        for(int i=0; i<len; i++)//枚举出所有子串,从开始位置到结束位置
        {
            for(int j=i+1; j<=len; j++)
            {
                if(judge(s,i,j))// 判断是否属于回文
                {
                    if(max<j-i)//属于更新最长长度
                    {
                        max = j-i;
                        st = s.substr(i,j-i);
                    }
                }
            }
        }
        return st;
        
    }
};
方法二:

由于我们要找一个字符作为中心点,所以要求改字符串要处理为奇数。只需要在代码中,将字符串长度变为2n+1即可,然后再还原原来实际的数组下标。例如数组babad可以处理为:#b#a#b#a#d# 然后c从元素b(下标为1处)开始为中心,此时i在下标为0处,j在下标为1处,此时要还原实际的下标,当c在奇数处的时候,i=(c-2)/2 j=(c+2)/2,所以i,j在数组babad中实际下标为0,1,则比较的是s[0],s[1]。同理若c在下标为4处的时候,此时c在偶数位置,i=(c-1)/2,j=(c+1)/2,所以实际下标为1,2则比较的是s[1],s[2](但是这个过程中会有重复比较)。若当s[i]!=s[j]的时候,移动c的位置。

char* longestPalindrome(char* s) {
    int n = strlen(s);
    char *p = (char *)malloc(n+1);
    int len = 2*n+1;//虚拟增加长度,使之始终为奇数
    int c,j,i,star,end;
    int max=0,count = 0;
    for(c=1; c<len; c++)
    {
        if(c%2==0)//若C移到的位置为虚拟长度中不存在的位置时候,即偶数位置时候
        {
            i = (c-1)/2;//映射到的i,j在实际数组中的位置
            j = (c+1)/2;
            while((i>=0)&&(j<n)&&(s[i]==s[j]))
            {
                count = j-i+1;//更新最长长度
                if(count>max)
                {
                    max = count;
                    star = i;
                    end = j;
                }
                i = i-1;
                j = j+1;
            }
        }
        else//当中心点移动到奇数位置,在字母上的情况
        {
            i = (c-2)/2;//还原i,j实际下标
            j = (c+2)/2;
            while((i>=0)&&(j<n)&&(s[i]==s[j]))
            {
                count = j-i+1;
                if(count>max)
                {
                    max = count;
                    star = i;
                    end = j;
                }
                i = i-1;
                j = j+1;
            }
        }
    }
    strncpy(p,s+star,(end-star+1));
    p[end-star+1]='\0';
    return p;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值