5. Longest Palindromic Substring

本文介绍了两种寻找字符串中最长回文子串的方法:一种是从中间向两边展开的O(N²)算法,另一种是Manacher算法,其时间复杂度为O(N)。文章通过实例详细解释了这两种算法的工作原理,并提供了完整的代码实现。

最长回文串

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

Example:

Input: "babad"

Output: "bab"

Note: "aba" is also a valid answer.

 

Example:

Input: "cbbd"

Output: "bb"

1.时间复杂度为O(N²)的算法-从中间向两边展开

回文字符串显然有个特征是沿着中心那个字符轴对称。比如aha沿着中间的h轴对称,a沿着中间的a轴对称。那么aa呢?沿着中间的空字符''轴对称。 所以对于长度为奇数的回文字符串,它沿着中心字符轴对称,对于长度为偶数的回文字符串,它沿着中心的空字符轴对称。 对于长度为N的候选字符串,我们需要在每一个可能的中心点进行检测以判断是否构成回文字符串,这样的中心点一共有2N-1个(2N-1=N-1 + N)。 检测的具体办法是,从中心开始向两端展开,观察两端的字符是否相同。代码如下:

//从中间向两边展开  
string expandAroundCenter(string s, int c1, int c2) {  
  int l = c1, r = c2;  
  int n = s.length();  
  while (l >= 0 && r <= n-1 && s[l] == s[r]) {  
    l--;  
    r++;  
  }  
  return s.substr(l+1, r-l-1);  
}  
   
string longestPalindromeSimple(string s) {  
  int n = s.length();  
  if (n == 0) return "";  
  string longest = s.substr(0, 1);  // a single char itself is a palindrome  
  for (int i = 0; i < n-1; i++) {  
    string p1 = expandAroundCenter(s, i, i); //长度为奇数的候选回文字符串  
    if (p1.length() > longest.length())  
      longest = p1;  
   
    string p2 = expandAroundCenter(s, i, i+1);//长度为偶数的候选回文字符串  
    if (p2.length() > longest.length())  
      longest = p2;  
  }  
  return longest;  
}  

2.Manacher算法:求解最长回文字符串,时间复杂度为O(N)

参考:https://segmentfault.com/a/1190000003914228

string longestPalindrome(string s) {
        string t ="$#";
        for (int i = 0; i < s.size(); ++i) {
            t += s[i];
            t += '#';
        }
        int p[t.size()] = {0}, id = 0, mx = 0, resId = 0, resMx = 0;
        for (int i = 0; i < t.size(); ++i) {
            p[i] = mx > i ? min(p[2 * id - i], mx - i) : 1;
            while (t[i + p[i]] == t[i - p[i]]) ++p[i];
            if (mx < i + p[i]) {
                mx = i + p[i];
                id = i;
            }
            if (resMx < p[i]) {
                resMx = p[i];
                resId = i;
            }
        }
        return s.substr((resId - resMx) / 2, resMx - 1);
    }

(一开始不理解为什么最后获取子串是((resId - resMx) / 2),因为里面填充了 “#”)

同时还有 http://blog.youkuaiyun.com/yzl_rex/article/details/7908259

            http://www.cnblogs.com/grandyang/p/4464476.html

转载于:https://www.cnblogs.com/wft1990/p/6941133.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值