给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例 2:
输入: “cbbd”
输出: “bb”
1、暴力解法
public class 最长回文字串 {
//暴力解法
public String longestPalindrome(String s){
int len=s.length();
if(len<2){
return s;
}
int maxLen=1;
int begin=0;
//转换成字符数组
char[] charArray=s.toCharArray();
//枚举所有长度严格大于1的字串 charArray[i...j]
//这里写出所有字串
for(int i=0;i<len;i++){
for(int j=i+1;j<len;j++){
if(j-i+1>maxLen&&validPalindromic(charArray,i,j))//将所有字串进行判断
maxLen=j-i+1;
begin=i;
}
}
return s.substring(begin,begin+maxLen);
}
//这里判断是否为回文字串
public boolean validPalindromic(char[] charArray,int left,int right){
while(left<right) {
if (charArray[left] == charArray[right]) {
return false;
}
left++;
right--;
}
return true;
}
}
O(n^3) O(n)
2、中心扩展算法
ublic class 最长回文字串2 {
public static String longestPalindrome(String s){
if(s==null||s.length()<1){
return "";
}
int start=0,end=0;
for(int i=0;i<s.length();i++){
int len1=expandAroundCenter(s,i,i);
int len2=expandAroundCenter(s,i,i+1);
int len=Math.max(len1,len2);
if(len>end-start){
start=i-(len-1)/2;
end=i+len/2;
}
}
return s.substring(start,end+1);
}
//找到最大的回文长度
public static int expandAroundCenter(String s,int left,int right){
while(left>=0&&right<s.length()&&s.charAt(left)==s.charAt(right)){
right++;
left--;
}
return right-left-1;
}
public static void main(String[] args){
System.out.println(longestPalindrome("asdasdasdasdadadad"));
}
}
O(n^2) O(1)
我们枚举所有的「回文中心」并尝试「扩展」,直到无法扩展为止,此时的回文串长度即为此「回文中心」下的最长回文串长度。我们对所有的长度求出最大值,即可得到最终的答案。
3、动态规划算法
public class 最长回文字串3 {
public static String longestPalindrome(String s){
int len=s.length();
if(len<2){
return s;
}
int maxLen=1;
int begin=0;
boolean[][] dp=new boolean[len][len];
for(int i=0;i<s.length();i++){
dp[i][i]=true;
}
char[] charArray=s.toCharArray();
for(int j=1;j<len;j++){
for(int i=0;i<j;i++){
if(charArray[i]!=charArray[j])//如果i元素与j元素不相等则不是回文字串
dp[i][j]=false;
else{//
if(j-i+1<3)//当长度小于3的字串就是回文字串
dp[i][j]=true;
else//当长度不小于3 且i元素与j元素相等时 就要看该位置的左下角位置是否为true
dp[i][j]=dp[i+1][j-1];
}
if(dp[i][j]&&j-i+1>maxLen){
maxLen=j-i+1;
begin=i;
}
}
}
return s.substring(begin,maxLen+begin);
}
}
O(n^2)
O(n^2)
4、Manacher 算法(仅做参考)
class Solution {
public String longestPalindrome(String s) {
int start = 0, end = -1;
StringBuffer t = new StringBuffer("#");
for (int i = 0; i < s.length(); ++i) {
t.append(s.charAt(i));
t.append(’#’);
}
t.append(’#’);
s = t.toString();
List<Integer> arm_len = new ArrayList<Integer>();
int right = -1, j = -1;
for (int i = 0; i < s.length(); ++i) {
int cur_arm_len;
if (right >= i) {
int i_sym = j * 2 - i;
int min_arm_len = Math.min(arm_len.get(i_sym), right - i);
cur_arm_len = expand(s, i - min_arm_len, i + min_arm_len);
} else {
cur_arm_len = expand(s, i, i);
}
arm_len.add(cur_arm_len);
if (i + cur_arm_len > right) {
j = i;
right = i + cur_arm_len;
}
if (cur_arm_len * 2 + 1 > end - start) {
start = i - cur_arm_len;
end = i + cur_arm_len;
}
}
StringBuffer ans = new StringBuffer();
for (int i = start; i <= end; ++i) {
if (s.charAt(i) != '#') {
ans.append(s.charAt(i));
}
}
return ans.toString();
}
public int expand(String s, int left, int right) {
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
--left;
++right;
}
return (right - left - 2) / 2;
}
}
O(n)
O(1)