最长回文算法

给你一个字符串 s,找到 s 中最长的回文子串。

如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

示例 1:

输入:s = "babad"

输出:"bab"

解释:"aba" 同样是符合题意的答案。

示例 2:

输入:s = "cbbd"

输出:"bb"

提示:

  • 1 <= s.length <= 1000

  • s 仅由数字和英文字母组成

思路:遇到这题,第一想法就是暴力求解。如下代码所示,枚举所有的子串,利用回文“反序与正序相同”的特性,判断是否回文。记录下最长的回文,并返回。当然,这种方法最终超时了。

class Solution {
public:
   string longestPalindrome(string s) {
         int maxstrlen=0;//最长回文子串长度
         string maxstring;//最长回文子串
         for(int i=0;i<s.size();i++)
         {
           for(int j=1;j<s.size()-i+1;j++)
           {
              int strlen=0;//回文子串长度
              string tempstr=s.substr(i,j);
              string fanzhuan=tempstr;
              reverse(fanzhuan.begin(),fanzhuan.end());
              if(fanzhuan==tempstr)
              {
                 strlen=tempstr.size();
                 if(maxstrlen<strlen)
                 {maxstring = tempstr;maxstrlen=strlen;}
              }
            }
         }
         return maxstring;
    }
};

以下方法采用中心扩散的方法。

如下图所示,对于已经是回文子串的s来说,同时向两边扩散,判断s的前一个与后一个字符是否相同。如相同,则扩散后的子串仍是回文串。若不同,则扩散后的子串不是回文串。

但是,该方法对于如下图所示的初始子串来说,肯定是不行的。因为只判断两边扩散的方法只会判定{b,b,a}是非回文。而忽略掉{b,b}子串。

所以需要对中心i向左或者向右扩散,找到重复的字符,加入回文子串,以防上述情况发生。

但是单边扩散仅限于回文中心位置。因为回文中心是重复字符的话,该中心必定符合回文性质。但是重复字符出现在回文非中心位置,则难以确认。

所以,以i为中心时,首先分别进行左右扩散,再进行中心扩散。详细如下所述。

首先,向左扩散找到相同的字符,并加入到回文子串中。直到遇到不相同的字符。

然后,向右扩散找到相同的字符,并加入到回文子串中。直到遇到不相同的字符。

最后,向左右两边同时扩散,找到两边对称的字符,双双加入回文子串中,直到两边字符不相称。

class Solution {
public:
 string longestPalindrome(string s) {
 int n=s.size();//n为字符串长度
 int maxlen=0;
 int maxstr=0;//最长回文子串的起始位置
 for(int i=0;i<n;i++)
 {
 int left=i-1;
 int right=i+1;
 int len=1;//以i为中心扩散时的子串长度
 while(left>=0&&s[left]==s[i]) {left--;len++;}//向左扩散
 while(right<=n-1&&s[right]==s[i]) {right++;len++;}//向右扩散
 while(left>=0&&right<=n-1&&s[left]==s[right])//向两边同时扩散
 {left--;right++;len+=2;}
 if(maxlen<len)
 {maxlen=len;maxstr=left+1;}
 }
 string maxstring;
 maxstring=s.substr(maxstr,maxlen);
 return maxstring;
 }
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值