Leetcode005-Longest Palindromic Substring
来源:互联网 发布:手机升温软件 编辑:程序博客网 时间:2024/05/14 22:28
Leetcode005-Longest Palindromic Substring
寻找最长回文子字符串
问题描述: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”
寻找最长回文子字符串问题,是一个经典的动态规划问题。首先,我们应当写出其动态转移方程。明显的,假如一个字符串收尾字母相同,且中间部分为回文字符串,那么该字符串为回文字符串。
record(i, j) ← ( record(i+1, j-1) and Si = Sj )
利用一个n2空间的数组就可以存储回文字符串的状态。然后采用回溯的方式找到对应的最长子回文串并输出。使用两重循环,时间复杂度为O(n2)
AC版本
class Solution {public: string longestPalindrome(string s) { string res; int length = s.size(); // 标记是否回文数 int record[length][length]; for(int i = 0; i<length; i++){ for(int j = 0; j<length; j++){ if ( j+i >= length) continue; if (i < 2) s[j] == s[j+i] ? record[j][j+i] = 1 : record[j][j+i] = 0; else if(s[j] == s[j+i]) record[j][j+i] = record[j+1][j+i-1]; else record[j][j+i] = 0; } } // 回溯 for(int i = length-1; i>=0; i--){ for(int j = 0; j<length; j++){ if ( j+i >= length ) continue; if (record[j][j+i]){ res = s.substr(j, i+1); return res; } } } }};
这个实现虽然通过了但是由于代码结构的问题,时间效率不高,调整后的代码结构如下:
class Solution {public: string longestPalindrome(string s) { string res; // 标记最长子回文串初始位置 int maxbegin = 0; // 标记最长子回文串长度 int maxlen = 1; int length = s.size(); // 标记是否回文数 bool record[length][length]; for(int i = 0; i<length; i++){ record[i][i] = true; if(i+1 < length){ if(s[i]==s[i+1]){ record[i][i+1] = true; maxlen = 2; maxbegin = i; } else record[i][i+1] = false; } } for(int sublen = 3; sublen<=length; sublen++){ for(int i = 0; i<length-sublen+1; i++){ int j = i + sublen - 1; if(s[i] == s[j] && record[i+1][j-1]){ record[i][j] = true; maxlen = sublen; maxbegin = i; } else record[i][j] = false; } } res = s.substr(maxbegin, maxlen); return res; }};
O(n)时间的算法
查阅相关资料,发现了一个时间复杂度的方法O(n),建议大家去这里查看原版的解答。本文剩余部分是对其的一些中文说明。
参数说明:
算法的主要步骤:
- 预处理,在字符串每一字符前后添加“#”进行分隔;
- 遍历字符串;
- 计算以当前元素为中心的回文子串的大小,存于sublen[]中;
- 若回文子串右端点>center为中心子串的右端点r,更新center和r。
算法举例: 字符串“abaca”,预处理为“#a#b#a#c#a#”。
如何计算以i为中心的子回文串长度:
这个部分算是这个算法的重点了,算法利用回文串的对称性,简化了计算子回文串长度的步骤,具体做法如下:
- 假设以i为中心的子回文串右端不超过以c为中心的子回文串右端
- 利用对称性,计算“a”( i=9)为中心的子串时,其子串长度与对称位置的“a”(i=5)的长度类似,此处相等,均为1;
- 也存在特殊,计算“b”( i=11)为中心的子串时,其子串长度本应与对称位置的“b”(i=3)的长度类似,但i=3处对应的回文串“aba”范围超出了以“c”为中心(图中橘色部分)的子串的范围,所以此处“b”的子串右端点应于“c”的子串右端点相同。(特意注明:此处i=13位置字符一定与i=1处不同,否则以“c”为中心的回文子串会更长)
- 假设以i为中心的子回文串右端超过以c为中心的子回文串右端
- 利用对称性,计算“b”( i=11)为中心的子串时,其子串长度至少应与对称位置的“b”(i=3)的长度相等,但i=11处对应的回文串“aba”范围超出了以“c”为中心(图中橘色部分)的子串的范围,所以需要对其进行扩展。(特意注明,扩展之后,要更新center和r)
- 利用对称性,计算“b”( i=11)为中心的子串时,其子串长度至少应与对称位置的“b”(i=3)的长度相等,但i=11处对应的回文串“aba”范围超出了以“c”为中心(图中橘色部分)的子串的范围,所以需要对其进行扩展。(特意注明,扩展之后,要更新center和r)
算法的时间复杂度:
从理论上解析,使用了两层循环(一层遍历,一层扩展)应当是O(n2)复杂度的,但实际上,扩展的越多表示对称覆盖的越广,这样导致需要扩展的元素越少。是一个相互制约的过程。这个算法的时间复杂度,需要使用平摊分析(amortized analysis)的方法进行分析。具体的我本人也没有分析过,(有时间的朋友可以分析一下,再留言。)在此略过。
AC版本
/** O(n)版本 */string preprocess(string s){ int n = s.size(); string res = "#"; for(int i=0; i<n; i++){ res += s[i]; res += "#"; } return res;}bool isvalid(string s, int n){ return n>=0 && n<s.size();}class Solution {public: string longestPalindrome(string s) { string str = preprocess(s); int n = str.size(); vector<int> sublen; int center = 0; int r = 0; int maxcenter = 0; int maxlen = 0; for(int i=0; i<n; i++){ // 按i为center遍历 if(r <= i) sublen.push_back(0); int sym_i = 2*center-i; // sym_i - center = center - i if(r > i) sublen.push_back( min(r-i, sublen[sym_i]) ); // 扩展i为中心的子回文串的右端点 while(true){ if(!isvalid(str, i+sublen[i]+1) || !isvalid(str, i-sublen[i]-1)) break; if(str[i+sublen[i]+1] == str[i-sublen[i]-1]) sublen[i]++; else break; } // i为中心的子回文串右端点在标记r的右侧,更新center和r if(i+sublen[i] > r){ center = i; r = i + sublen[i]; } if(sublen[i]>maxlen){ maxlen = sublen[i]; maxcenter = i; } // cout << sublen[i] << " "; } return s.substr((maxcenter+1-maxlen)/2,maxlen); }};
- leetcode005:Longest Palindromic Substring
- leetcode005 Longest Palindromic Substring
- Leetcode005-Longest Palindromic Substring
- LeetCode005 Longest Palindromic Substring
- Leetcode005. Longest Palindromic Substring
- LeetCode: Longest Palindromic Substring
- LeetCode Longest Palindromic Substring
- LeetCode: Longest Palindromic Substring
- [Leetcode] Longest Palindromic Substring
- Longest Palindromic substring
- [LeetCode] Longest Palindromic Substring
- LeetCode5:Longest Palindromic Substring
- Leetcode : Longest Palindromic Substring
- Longest Palindromic Substring
- Longest Palindromic Substring
- [LeetCode]Longest Palindromic Substring
- leetcode Longest Palindromic Substring
- Longest Palindromic Substring
- u-boot-1.1.6移植笔记(初级篇)
- 制作 Swift 和 Objective-C Mixed 的 Pod
- 51Nod-1319-跳跃游戏(三角形定理)
- Collection之List集合
- windows系统中安装ispin
- Leetcode005-Longest Palindromic Substring
- mongoose学习笔记一
- day15:JavaScript DOM编程学习笔记07
- POJ 1979
- 37-1-book2
- SPOJ Make Triangle 卡特兰数,递推 1月25日
- lampp下修改数据库的密码
- MySQL数据导出与导入
- hdu2222