标签:
问题: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 };
【Leetcode】Longest Palindromic Substring
标签:
原文地址:http://www.cnblogs.com/coolqiyu/p/5597744.html