原题地址:https://leetcode-cn.com/problems/longest-palindromic-substring/description/
题目描述:
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。
示例 1:
输入: "babad" 输出: "bab" 注意: "aba"也是一个有效答案。
示例 2:
输入: "cbbd" 输出: "bb"
解题方法:
string longestPalindromeDP(string s) {
int n = s.length();
int longestBegin = 0;
int maxLen = 1;
bool table[1000][1000] = {false};
for (int i = 0; i < n; i++) {
table[i][i] = true;
}
for (int i = 0; i < n-1; i++) {
if (s[i] == s[i+1]) {
table[i][i+1] = true;
longestBegin = i;
maxLen = 2;
}
}
for (int len = 3; len <= n; len++) {
for (int i = 0; i < n-len+1; i++) {
int j = i+len-1;
if (s[i] == s[j] && table[i+1][j-1]) {
table[i][j] = true;
longestBegin = i;
maxLen = len;
}
}
}
return s.substr(longestBegin, maxLen);
}
时间复杂度为f O(N2) ,空间复杂度也为f O(N2) 。table二维数组是精髓,记录每个字符是否和后继字符相同。该方法先对一位和两位字符串进行判断,更新table二维数组,再对长度为三以上的字符进行判断,对数组进行更新。
longestBegin和maxLen的用法也值得学习:
basic_string::substr
basic_string substr(
size_type _Off = 0,size_type _Count = npos) const;
参数
_Off
所需的子字符串的起始位置。
字符串中第一个字符的索引为 0,默认值为0.
_Count
复制的字符数目
返回值
一个子字符串,从其指定的位置开始
- string x="Hello_World";
- /*默认截取从0到npos.重载原型为string substr(_off=0,_count=npos);npos一般表示为string类中不存在的位置,_off表示字符串的开始位置,_count截取的字符的数目*/
- cout<<x.substr()<<endl;
- cout<<x.substr(5)<<endl;//截取x[5]到结尾,即npos.重载原型为string substr(_off,_count=npos)
- cout<<x.substr(0,5)<<endl;//以x[0]为始,向后截取5位(包含x[0]),重载原型string substr(_off,_count)
优化方法:
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;
}
i代表测试字符串的下标,对字符串进行遍历,传回回旋字符串。这种遍历要进行两次,因为考虑到奇数个回旋和偶数个回旋。