LeetCode题解——Longest Palindromic Substring

题目

给定一个字符串S,返回S中最长的回文子串。S最长为1000,且最长回文子串是唯一。

 

解法

①遍历,对于每个字符,计算以它为中心的回文子串长度(长度为奇数),同时计算以它和右边相邻字符为中心的回文子串长度(长度为偶数)。时间为O(N2)。

②另外,有一个很奇妙的算法,称为Manacher算法,参考 http://www.cnblogs.com/daoluanxiaozi/p/longest-palindromic-substring.html ,时间为O(N)。

 

代码

①直接扩展:

 1 class Solution {  2 public:  3     string longestPalindrome(string s) {  4         int start = 0, max_len = 0;  5         for(int i = 0; i < s.size(); ++i)  6  {  7             int left, right, len;  8             

 9             len = 1;    //以当前字符为中心的回文串 10             for(left = i - 1, right = i + 1; left >= 0 && right < s.size() && s[left] == s[right]; --left, ++right) 11                 len += 2; 12             if(len > max_len) 13  { 14                 start   = left + 1; 15                 max_len = len; 16  } 17             

18             len = 0;    //以当前字符以及右边相邻字符为中心的回文串 19             for(left = i, right = i + 1; left >= 0 && right < s.size() && s[left] == s[right]; --left, ++right) 20                 len += 2; 21             if(len > max_len) 22  { 23                 start   = left + 1; 24                 max_len = len; 25  } 26  } 27         return s.substr(start, max_len); 28  } 29 };

②Manacher算法:

 1 class Solution {  2 public:  3     string longestPalindrome(string s) {  4         int slen = s.size();  5         if(slen == 0 || slen == 1)  6             return s;  7         

 8         const int nslen = 2 * slen + 3;  //每个字符两边填充#,将奇偶长度的回文串统一处理

 9         string ns(nslen, '#'); 10         ns[0]         = '^';     //开始和结尾添加特殊字符,防止越界 11         ns[nslen - 1] = '$'; 12         for(int i = 0; i < slen; ++i) 13             ns[2 * i + 2] = s[i]; 14             

15         int id = 0, mx = 0;  //id为已找到的最右回文串的中心下标,mx为该回文串的最右下标 16         int p[nslen];        //p保存以每个字符为中心的回文串的半径,这个半径值就是去掉填充字符之后实际回文串长度 17         

18         for(int i = 1; i < nslen - 1; ++i) 19  { 20             p[i] = mx > i ? min(mx - i, p[2 * id - i]) : 0;  //利用已有信息,给当前字符为中心的回文串赋半径初值 21             

22             while(ns[i - 1 - p[i]] == ns[i + 1 + p[i]])      //向两边扩张 23                 ++p[i]; 24             

25             if(i + p[i] > mx) 26  { 27                 mx = i + p[i]; 28                 id = i; 29  } 30  } 31         

32         int mid = 0, max_len = 0; 33         for(int i = 1; i < nslen - 1; ++i)       //找出最长的回文串 34             if(p[i] > max_len) 35  { 36                 mid = i; 37                 max_len = p[i]; 38  } 39             

40         return s.substr((mid - 1 - max_len)/2, max_len);   //求出回文串第一个字符的下标,返回回文串 41  } 42 };

 

你可能感兴趣的:(substring)