Question:
给定一个字符串,输出其中最长的回文子串。
几种解法:
暴力枚举:时间复杂度:O(n3)(略)
(双层枚举:O(n2)判断是否为回文串:O(n))
动态规划:时间复杂度O(n2),空间复杂度O(n2 )运用普遍的解法,此处耗时较久、空间较大。(略)
中心扩散(推荐):
时间复杂度O(n2),空间复杂度O(1)
C++代码:
class Solution {
public:
string longestPalindrome(string s) {
if (s.size() < 2)return s;
int begin = 0, maxsize = 0;
int n;
for (int i = 0; i < s.size() - 1; i++) {//枚举中心位置
int oddlen = expandCenter(s, i, i);//以i为中心向两边扩散
int evenlen = expandCenter(s, i, i + 1);//以i和i+1为中心向两边扩散
n = max(oddlen, evenlen);//取大的串长
if (n > maxsize) {
maxsize = n;
begin = i - (maxsize - 1) / 2;//画图易得串起始位置(关键)
}
}
return s.substr(begin, maxsize);
}
int expandCenter(string& s, int right, int left) {//中心扩散函数
int i = right;
int j = left;
for (; i >= 0 && j <= s.size() - 1;i--,j++) {
if (s[i] == s[j]) continue;
else break;
}
return j-i+1-2; //返回当前回文串长(画图易得j-i+1为串长,)
//(-2是最后跳出循环坐标移动的值)
}
};
中心扩散:
用下标 【i】【j】 记录某个中心位置,将下标向两边以相同速率扩散(i - -,j ++),当【i】!=【j】时停止扩散。
在本题的使用思路:
枚举每个可能的中心位置(包含子串以一个元素或两个元素为中心位置的情况),每次枚举调用 中心扩散函数 ,得到当前中心位置的回文子串长度,与已得到的最大回文子串长度相比较、取最大值,并记录此串的起始位置 begin,枚举结束即可得到答案。
中心扩散函数(expandCenter):
int expandCenter(string& s, int right, int left) {//中心扩散函数
int i = right;
int j = left;
for (; i >= 0 && j <= s.size() - 1;i--,j++) {
if (s[i] == s[j]) continue;
else break;
}
return j-i+1-2; //返回当前回文串长(画图易得j-i+1为串长,)
//(-2是最后跳出循环坐标移动的值)
}