【Leetcode】Longest Palindromic Substring

问题:https://leetcode.com/problems/longest-palindromic-substring/

给定一个字符串 S,求出 S 的最长回文子串

思路:

1. 回文:一个字符串从前和从后读一致。S = "ABBA"  从前读:ABBA,从后读:ABBA

2. 最简单的做法:列出所有的子串,并判断是否是回文,从中找出最长的。

  表格列出了所有的子串,第 i 行是以 S 的第 i 个字符开始的子串。S = "ABBA"

 1  A  AB  ABB  ABBA
 2      B    BB    BBA
 3          B      BA
 4              A

 从最后一行往上,可以看到他们的共同部分,用红色标出。共同的子问题~动态规划。

3. 动态规划,自底向上求解问题 

  1) 对子问题的结果进行存储和表示

  len[i]:包含S[i] 的最长回文子串的长度

  all[i]:S 的后半部分S[i, ..., n - 1] 中的最长回文子串长度 

  2) 把子问题的结果合并成它的上一层

   子问题比它的上一层增加了一个字符。已经求得 S[i+1, ...] 子问题的解:从S[i+1]开始有len[i+1]长的回文子串 S[i+1]~S[n], all[i+1]

   

  ** 如果S[i]和这个子串的后一个字符一样,则从S[i]开始的回文子串可以包含它

  比如:S="ABBA",已知 len[1] = 2,S[0]=S[3]="A",所以len[0] = len[1]+2

  ** 反之,从S[i]开始的回文子串不可以包含它,则需要对该子串从两头开始遍历

      用两个变量分别从头 S[i] 和从尾S[n+1]开始比较,当发生不等的时候,就重新从头开始。

源码 

 1 class Solution {
 2 public:
 3     string longestPalindrome(string s) {
 4         int ssize = s.length();
 5         int i, j, k, start;
 6         int* len = new int[ssize];
 7         int* all = new int[ssize];
 8         //初始化,最长为1
 9         len[ssize - 1] = all[ssize - 1] = 1;
10         start = ssize - 1;
11         
12         for(i = ssize - 2; i >= 0; --i)
13         {
14             //计算len[i]
15             if(i + len[i + 1] + 1 < ssize && s[i] == s[i + len[i + 1] + 1])//从S[i] 开始的回文子串包含S[i+1]开始的子串
16                 len[i] = len[i + 1] + 2;
17             else//反之需要遍历
18             {
19                 //j, k 表示从S[i] 开始可能的最长回文子串的区间
20                 j = i;
21                 k = i + len[i + 1];
22                 while(j < k)
23                 {
24                     if(s[j] == s[k])
25                     {
26                         ++j;
27                         --k;
28                     }
29                     else//两个字符不同时,j 需从头重新开始
30                     {
31                         j = i;
32                         --k;
33                     }
34                 }
35                 if(i == k && k == j)//
36                     len[i] = 1;
37                 else
38                 {
39                     len[i] = (k - i + 1) * 2;//子串长度为偶数
40                     if(j == k)//子串长度为奇数
41                       len[i]--;
42                 }
43             }
44             //计算all[i]
45             if(len[i] > all[i + 1])
46             {
47                 all[i] = len[i];
48                 start = i;
49             }
50             else
51             {
52                 if(len[i] == all[i + 1])
53                     start = i;
54                 all[i] = all[i + 1];
55             }
56         }
57         delete[] len;
58         delete[] all;
59         return s.substr(start, all[0]);
60     }
61 };
View Code
原文地址:https://www.cnblogs.com/coolqiyu/p/5597744.html