题目
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
解题思路
1.暴力法
#python
def get_longest_Palindromic(s):
window = 0
max_len = ""
while(window <= len(s)):
for i in range(int(len(s))):
if i+window >int(len(s)):
window +=1
break
if ispalindromic(s[i:i+window]):
max_len = s[i:i+window]
window +=1
break
return max_len
def ispalindromic(s):
if len(s)%2 == 0:
mid_index = int(len(s)/2)
else:
mid_index = int(len(s)/2+1)
for i in range(mid_index):
if s[i] != s[-(i+1)]:
return False
return True
由于要判断是否为回文,所以时间复杂度为,空间复杂度为,并不能AC.
2.动态规划法
动态规划相关知识可以点击链接。
#python
class Solution(object):
def longestPalindrome(self, s):
dp = [[0]*len(s) for i in range(len(s))]
max_len = 0
max_str = ""
for l in range(len(s)):
l = l+1
for start in range(len(s)):
end = start+l-1
if end >= len(s):
break
dp[start][end] = (l==1) or (l==2 and (s[start]==s[end])) or (dp[start+1][end-1] and (s[start]==s[end]))
if dp[start][end] and max_len
动态规划也可以看作是一种更聪明的暴力法,因为可以减少重复计算。时间复杂度和空间复杂度都是
3.中心扩展
我们观察到回文中心的两侧互为镜像。因此,回文可以从它的中心展开,并且只有 2n−1 个这样的中心。你可能会问,为什么会是 2n−1 个,而不是 n 个中心?原因在于所含字母数为偶数的回文的中心可以处于两字母之间(例如 “abba” 的中心在两个 ‘b’ 之间)。
#python
def get_longest_Palindromic_1(s):
max_len = 0
s_t = ""
for i in range(len(s)):
len1 = expandAroundCenter(s,i,i)#奇数回文串
len2 = expandAroundCenter(s,i,i+1)#偶数回文串
len_3 = max(len1,len2)
if max_len< len_3:
max_len = len_3
s_t = s[i-int((max_len-1)/2):i+int(max_len/2)+1]
return s_t
def expandAroundCenter(s,left,right):
while(left>=0 and right < len(s) and s[left] == s[right]):
left = left-1
right = right +1
return right-left-1
中心扩展时间复杂度,空间复杂度
Mnacher(马拉车)
算法详情点击链接.
#java
public String preProcess(String s) {
int n = s.length();
if (n == 0) {
return "^$";
}
String ret = "^";
for (int i = 0; i < n; i++)
ret += "#" + s.charAt(i);
ret += "#$";
return ret;
}
// 马拉车算法
public String longestPalindrome2(String s) {
String T = preProcess(s);
int n = T.length();
int[] P = new int[n];
int C = 0, R = 0;
for (int i = 1; i < n - 1; i++) {
int i_mirror = 2 * C - i;
if (R > i) {
P[i] = Math.min(R - i, P[i_mirror]);// 防止超出 R
} else {
P[i] = 0;// 等于 R 的情况
}
// 碰到之前讲的三种情况时候,需要利用中心扩展法
while (T.charAt(i + 1 + P[i]) == T.charAt(i - 1 - P[i])) {
P[i]++;
}
// 判断是否需要更新 R
if (i + P[i] > R) {
C = i;
R = i + P[i];
}
}
// 找出 P 的最大值
int maxLen = 0;
int centerIndex = 0;
for (int i = 1; i < n - 1; i++) {
if (P[i] > maxLen) {
maxLen = P[i];
centerIndex = i;
}
}
int start = (centerIndex - maxLen) / 2; //最开始讲的求原字符串下标
return s.substring(start, start + maxLen);
}