给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例 2:
输入: “cbbd”
输出: “bb”
来源:力扣(LeetCode)
https://leetcode-cn.com/problems/longest-palindromic-substring/
方法一:
O(n^2)。找到对称中心, 然后以对称中心向两旁扩, 从而找出最长回文子串。
class Solution {
public String longestPalindrome(final String s) {
if(s.length()==0)
return "";
int maxlen = 1;
int L=0, R=0;
for(int i = 0;i < s.length();i++){
int l = i-1;
int r = i+1;
int len = 1;
while(l>=0&&r<s.length()&&s.charAt(l)==s.charAt(r)){
l--;
r++;
len+=2;
}
if(len > maxlen){
maxlen = len;
L = l+1;
R = r-1;
}
}
for(int i = 0;i < s.length();i++){
int l = i;
int r = i+1;
int len = 0;
while(l>=0&&r<s.length()&&s.charAt(l)==s.charAt(r)){
l--;
r++;
len+=2;
}
if(len > maxlen){
maxlen=len;
L = l+1;
R = r-1;
}
}
return s.substring(L, R+1);
}
}
方法2:
O(n)级别, Manacher算法
class Solution {
public String longestPalindrome(String s) {
return Manacher(s);
}
public static char[] preProcess(String s){
int len = s.length();
char[] t = new char[len*2+3];
t[0] = '$';
t[1] = '#';
int j = 2;
for(int i = 0;i < len;i++){
t[j++] = s.charAt(i);
t[j++] = '#';
}
t[j] = '\0';
return t;
}
public static void init(int[] a){
for (int i = 0;i < a.length;i++){
a[i] = 1;
}
}
public static String Manacher(String s){
// if(s == null) return 0;
int[] Len = new int[s.length()*2+3];
char[] t = preProcess(s);
int r= 0;
int p=0, po=0,max_len = 0;
for(int i = 1;i < t.length-1;i++){
if(i < p){
Len[i] = Math.min(p-i, Len[2*po-i]);
}
else Len[i] = 1;
try{
while(t[i-Len[i]] == t[i+Len[i]])
Len[i]++;
}catch(Exception e){
System.out.println(i+Len[i]);
System.out.println(s);
System.out.println(i);
System.out.println(Len[i]);
System.out.println(t);
}
if(i+Len[i]-1 > p){
po=i;
p = i+Len[i]-1;
}
if (max_len < Len[i]-1){
max_len=Len[i]-1;
r = i+Len[i]-1;
}
}
return s.substring((r-1)/2 -max_len, (r-1)/2);
}
}
2020-6-8