题目描述:找出最长回文子串(LPS)
题目链接:Leetcode 5. Longest Palindromic Substring
这个问题目前为止看到3个想法:
1、马拉车算法巧妙的O(n)算法,分情况讨论,利用回文的对称性来更新结果
2、动态规划算法(d[i…j])是否为回文,然后2层循环
3、KMP利用最长前缀匹配算法来做。
4、暴力搜索(主要是穷举子串、子数组的训练)
参考链接处有更多的做法思路最重要的思路就是插入#
让奇数成偶数。
代码如下
#马拉车 前几次做法
class Solution:
def longestPalindrome(self, s: 'str') -> 'str':
if not s or len(s) == 0:
return ""
ans = s[-1]
ns = "#" + "#".join(s) + "#" # 可解决奇数偶数问题
pArr = [0 for _ in range(len(ns))] #回文半径数组
index = -1 # 回文最右边界中心
pR = -1 # 回文最右边界
maxN = -(1 << 31)
for i in range(len(ns)):
pArr[i] = min(pArr[2 * index - i], pR - i) if pR > i else 1 # 获取要么外扩为1 要么就是内情况和外情况
while (i + pArr[i] < len(ns) and i - pArr[i] > -1):
if (ns[i + pArr[i]] == ns[i - pArr[i]]): #扩大半径
pArr[i] += 1
else:
break
if (i + pArr[i] > pR): #由于对称 看是在边界内 边界上还是边界外 更新边界
pR = i + pArr[i]
index = i #更新回文中心
if pArr[i] > maxN: #更新了回文串
maxN = max(maxN, pArr[i])
ans = ns[i-pArr[i]+1:i+pArr[i]].replace("#","")
# print()
return ans
class Solution {
public String longestPalindrome(String s) {
// 先来个暴力求解
int l = s.length();
if (l == 0){
return s;
}
String ans = s.substring(0,1);
for (int i = 1; i < l; i++) {
for (int j = 0; j < i; j++) { // 以i结尾的子串。
if ((i + 1 - j) > ans.length()) {
String subs = s.substring(j, i + 1);
if (subs.equals(new StringBuffer(subs).reverse().toString())) {
ans = s.substring(j, i + 1);
}
}
}
}
return ans;
}
}