首页 > 试题广场 >

最长回文子串

[编程题]最长回文子串
  • 热度指数:234031 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解

对于长度为n的一个字符串A(仅包含数字,大小写英文字母),请设计一个高效算法,计算其中最长回文子串的长度。


数据范围:
要求:空间复杂度 ,时间复杂度
进阶:  空间复杂度 ,时间复杂度
示例1

输入

"ababc"

输出

3

说明

最长的回文子串为"aba"与"bab",长度都为3
示例2

输入

"abbba"

输出

5
示例3

输入

"b"

输出

1

方法1:中心扩展法

public class Solution {
    // 方法1:遍历,时间复杂度为 O(n^2)
    public int getLongestPalindrome(String A, int n) {
        int maxLen = Integer.MIN_VALUE;
        for (int i = 0; i < n; i++) {
            // 这里一定要注意奇数长度和偶数长度的回文串都要考虑
            maxLen=Math.max(maxLen,getMaxHui(i-1,i+1,A));
            maxLen=Math.max(maxLen,getMaxHui(i,i+1,A));
        }
        return maxLen;
    }

    // 获取指定 l r 开始的最长的回文串长度
    private int getMaxHui(int l,int r,String A) {
        while (l>=0 && r<=A.length()-1 && A.charAt(l)==A.charAt(r)) {
            l--;
            r++;
        }
        return r-l-1;
    }
}

方法2:动态规划

public class Solution {
   public int getLongestPalindrome(String A) {
       if (A.length()<=1) return A.length();
        int n = A.length();
        int[][] dp = new int[n][n];
        int res = 1;
        int len = A.length();
        // 长度为 1 的串,肯定是回文的
        for (int i = 0; i < n; i++) {
            dp[i][i]=1;
        }
        // 将长度为 2-str.length 的所有串遍历一遍
        for (int step = 2; step <= A.length(); step++) {
            for (int l = 0; l < A.length(); l++) {
                int r=l+step-1;
                if (r>=len) break;
                if (A.charAt(l)==A.charAt(r)) {
                    if (r-l==1) dp[l][r]=2;
                    else dp[l][r]=dp[l+1][r-1]==0?0:dp[l+1][r-1]+2;
                }
                res=Math.max(res,dp[l][r]);
            }
        }
        return res;
    }
}
发表于 2021-11-17 15:44:35 回复(2)
public int getLongestPalindrome(String A, int n) {
        if(n == 0) return 0;
        if(n == 1) return 1;

        int maxLen = 1;
        for(int i = 0; i<n; i++){
            for(int j = 1; i-j>=0 && i+j<n; j++){
                if(A.charAt(i-j) == A.charAt(i+j)){
                    int len = 2*j+1;
                    maxLen = Math.max(len,maxLen);
                }
                if(A.charAt(i-j) != A.charAt(i+j))break;
            }

            for(int k = 1; i-k+1>=0 && i+k<n; k++){
                if(A.charAt(i-k+1) == A.charAt(i+k) ) {
                    int len = 2*k;
                    maxLen = Math.max(len,maxLen);
                }
                if(A.charAt(i-k+1) != A.charAt(i+k)) break;
            }
        }
   
        return maxLen;
    }

发表于 2021-08-21 14:52:05 回复(0)
#马拉车中心扩散
class Solution:
    def getLongestPalindrome(self, A, n):
        strin = []
        A = list(A)
        A.reverse()
        for i in range(2*n+1):
            if i % 2 == 0:
                strin.append('*')
            else:
                strin.append(A.pop())
        maxr = 0
        for index,item in enumerate(strin):
            step = 1
            try:
                while strin[index-step] == strin[index+step]:
                    step+=1
            except:
                rest = step - 1
                if rest > maxr:
                    maxr = rest
                continue
            rest = step - 1
            if rest > maxr:
                maxr = rest
        return maxr
发表于 2021-07-31 21:34:23 回复(0)
我是直接循环与下一个或者下下一个字符比对,哪位大佬能看出来我哪出错了
用例输入: "dacbcbcabacaabcbcbdaaccacdddabdbcdcdbdabccbdababdaccbbbaccdaaacbbdcdadcacdbcbcacacaddbcbbcadccacdaabddacbcbbcdcadcbbcdddccdccdcbbbaabdadabdbbcbababacbbddbcdbdbbdabaaaaabacadbadbbadabccbbadbcdbcbaadbbddcacdbacadccbccdbacabacaacdbdcbcabbbccdadcbaccccccaaacbbbcbacdadaadcdbacaaadcbdccbcbcdacbababbc",295
预期输出 9
实际输出 8
class Solution {
public:
    int getLongestPalindrome(string A, int n) {
        // write code here
        int Max = 0,i = 0,j = 0,k = 0,tmp = 0;
        for(i = 0; i < n;i++)
        {
            if(A[i] != A[i + 1] && A[i] != A[i + 2])
            {
                continue;
            }else{
                if(A[i] == A[i + 1])
                {
                    if(A[i] != A[i + 2])
                    {
                        tmp = 2;
                        k = i+2;
                    }else{
                        if(A[i - 1] == A[i + 2])
                        {
                            tmp = 2;
                            k = i+2;
                        }else{
                            tmp = 3;
                            k = i + 3;
                        }
                    }
                }else if(A[i] == A[i + 2])
                {
                    tmp = 3;
                    k = i + 3;
                }
                for(j = i-1;j >= 0 && k <= n;j--,k++)
                {
                    if(A[j] == A[k])
                    {
                        tmp += 2;
                    }else{
                        break;
                    }
                }
                if(Max < tmp)
                    Max = tmp;
            }
        }
        return Max;
    }
};
发表于 2021-06-24 02:15:03 回复(0)
时间复杂度:o(n)

import java.util.*;

public class Solution {
    public int getLongestPalindrome(String A, int n) {
        // write code here
        char[] chars = A.toCharArray();
        int max = 1;
        int left,right;
        for(int i = 0 ; i < n;i++){
            int res1 = process(chars,i-1,i+1,n,1);
            int res2 = process(chars,i,i+1,n,0);
            int count = Math.max(res1,res2);
            max = Math.max(count,max);
        }
        return max;
    }
    
    public int process(char[] chars , int left,int right,int n,int count){

        while(left>=0 && right<n){
                  if(chars[left] != chars[right]){
                    break;
                }
                count+=2;
                left--;
                right++;
            }
        return count;
    }
    
}

编辑于 2021-05-18 15:03:47 回复(0)

//动态规划
int getLongestPalindrome(string A, int n) {
        // write code here
        int res=1;
        vector<vector<bool>> dp(n,vector<bool>(n,false)); //dp[i][j]:从i到j的字符子串是不是回文串
        for(int i=0; i<n; i++)
        {
            dp[i][i]=true;
        }
        for(int j=1; j<n; j++)
        {
            for(int i=0; i<j; i++)
            {
                if(A[i]!=A[j])
                    dp[i][j]=false;
                else
                {
                    if(j-i+1<=3)  //如果长度小于等于3,直接就是回文串
                        dp[i][j]=true;
                    else //长度大于等于4
                        dp[i][j]=dp[i+1][j-1];
                }
                
                if(dp[i][j] && j-i+1>res)  //更新最大长度
                    res = j-i+1;
            }
        }
        return res;

//中心扩散
    int sublen(string& A, int l, int r)
    {
        while(l>=0 && r<A.size() && A[l]==A[r])
        {
            l--;
            r++;
        }
        return r-l-1;
    }
    
    int getLongestPalindrome(string A, int n) {
        int res=1;
        for(int i=0; i<n; i++)
        {
            int r1 = sublen(A, i, i);
            int r2 = sublen(A, i, i+1);
            
            res = res>r1?res:r1;
            res = res>r2?res:r2;
        }
        return res;
    }



编辑于 2021-05-14 18:02:00 回复(0)
暴力解法,数据量小就可以,要是数据量大就会超时了
import java.util.*;

public class Solution {
    public int getLongestPalindrome(String A, int n) {
        // write code here
        if(n<2){
            return n;
        }
        int maxLength=1;
        int begin=0;
        char[] chararray=A.toCharArray();
        for(int i=0;i<n-1;i++){
            for(int j=i+1;j<n;j++){
                if(j-i+1>maxLength && validPalindrome(chararray,i,j)){
                    maxLength=j-i+1;
                    begin=i;
                }
            }
        }
        return maxLength;
    }
    public boolean validPalindrome(char[] chararray,int left,int right){
        while(left<right){
            if(chararray[left]!=chararray[right]){
                return false;
        }
            left++;
            right--;
        }
        return true;
    }
}


发表于 2021-04-16 20:18:39 回复(0)
import java.util.*;
//喜极而泣啊!写代码五分钟,调bug2小时
//说下思路:
public class Solution{
public int getLongestPalindrome(String A, int n) {
            char [] strArr = A.toCharArray();
            int length=0;
    		// l为左,r为右,当l到r范围的字符串为回文,(两端相等,并依次递归,直到所有相等,则为回文)
    		for (int l=0; l < n; l++) {
			for (int r = l; r < n; r++) {
                //设置一个flag,当回文时为1,不回文为-1
                int flag=0,r1=r,l1=l;
                while(l1<=r1)
                {
                    if(strArr[l1]==strArr[r1])
                        flag=1;
                    else
                    {flag=-1;break;}
                    l1++;
                    r1--;
                }
                if(flag==1)length=Math.max(length,r-l+1);
                }
		}
    		return length;
    }
}

发表于 2021-04-02 22:00:11 回复(0)
import java.util.*;

public class Solution {
    public int getLongestPalindrome(String A, int n) {
        // write code here
        int [][] dp = new int [n+1][n+1];
        int res = 1;
        for(int i = 0;i < n;++i)
            dp[i][i] = 1;
        for(int i = 0,j = i+1;i < n && j < n;++i,++j){
            if(A.charAt(i) == A.charAt(j)){
                dp[i][j] = 2;
                res = 2;
            }    
            else
                dp[i][j] = 0;
        }
        int dis = 2;
        while(dis < n){
            for(int i = 0,j = i+dis;j < n;++i,++j){
                 if(A.charAt(i) == A.charAt(j) && dp[i+1][j-1] != 0){
                    dp[i][j] = 2+dp[i+1][j-1];
                    res = Math.max(dp[i][j],res);
                 }else
                     dp[i][j] = 0;    
            }
            ++dis;
        }
        return res;     
    }
}

发表于 2021-03-29 19:27:56 回复(0)
解题思路:动态规划,len从短到长遍历,dp[i][j]表示从位置i到位置j的最大回文子串长度
import java.util.*;
public class Solution {
    public int getLongestPalindrome(String A, int n) {
        // write code here
        int[][] dp = new int[n][n];
        int max = 1;
        for (int i = 0; i < n; ++i) {
            dp[i][i] = 1;
        }
        char[] a = A.toCharArray();
        for(int len=2;len<=n;++len){
            for(int i=0;i<=n-len;++i){
                int j=i+len-1;
                if(len==2&&a[i]==a[j]){
                    dp[i][j]=2;
                    if(max<2) max=2;
                }
                if(a[i]==a[j]&&dp[i+1][j-1]!=0){
                    dp[i][j]=len;
                    if(max<len) max=len;
                }
            }
        }
        return max;
    }
}
发表于 2021-03-15 09:35:47 回复(0)
export function getLongestPalindrome(A: string, n: number): number {
    // write code here
   if(!n) return 0
    let res = 1
    const dp = []
    for(let i = n -1;i>=0;i--){
        dp[i] = []
        for(let j = i;j<n;j++){
            if(j - i == 0) dp[i][j] = true
            else if(A[i] == A[j]&&j-i == 1) dp[i][j] = true
            else if(A[i] == A[j] && dp[i+1][j-1]) dp[i][j] = true
            if( dp[i][j]&& j - i + 1 >res)  res = j - i + 1
        }
    }
        return res
}

发表于 2021-01-07 19:25:17 回复(0)
import java.util.*;

public class Solution {
    public int getLongestPalindrome(String A, int n) {
        int maxCount = 0;
        for (int i = 1; i < A.length() ; i++){
            int left = i -1;
            int right = i +1;
            int count = 1;
            maxCount = getMaxCount(A, maxCount, left, right, count);
            left = i -1;
            right = i;
            count = 0;
            maxCount = getMaxCount(A, maxCount, left, right, count);
        }
        // write code here
        return maxCount;
    }

    private int getMaxCount(String A, int maxCount, int left, int right, int count) {
        while (left>= 0 && right <= A.length()-1 && A.charAt(left) == A.charAt(right)){
            left--;
            right++;
            count+=2;
        }
        maxCount = Math.max(count,maxCount);
        return maxCount;
    }
}


发表于 2020-11-08 21:53:32 回复(0)
class Solution {
public:
    int getLongestPalindrome(string s, int n) {
         int res=0;int l,r;
        for(int i=0;i<n;i++)
        {
             l=i-1; r=i+1;
            while(l>=0&&r<=n-1&&s[l]==s[r])
            {
                res=max(res,r-l+1);
                l--;r++;
            }
            
            l=i;r=i+1;
            while(l>=0&&r<=n-1&&s[l]==s[r])
            {
                res=max(res,r-l+1);
                l--;r++;
            }
          
        }
        return res;
        
    }
};//借鉴某位大神的写法写了一遍
发表于 2020-09-04 17:00:20 回复(0)
class Solution {
public:
    int getLongestPalindrome(string A, int n) {
        if (n < 2) return n;
        
        int max = 1;
        
        for (int i = 0; i < n; i++) {
            for (int j = 1; i-j >= 0 && i+j < n; j++)
            {
                if (A[i-j] == A[i+j]) {
                    int t = j*2 + 1;
                    max = t > max ? t : max;
                } else
                    break;
            }
            
            for (int j = 0; i-j-1 >= 0 && i+j <n; j++) {
                if (A[i-j-1] == A[i+j]) {
                    int t = j*2 + 2;
                    max = t > max ? t : max;
                } else
                    break;
            }
        }
        return max; 
    }
    
   
    
};

发表于 2020-03-29 00:56:00 回复(0)
//详情请点击博客链接(链接在最下方)
import java.util.*;

public class Solution {
    public int getLongestPalindrome(String A, int n) {
        // write code here
        int count=0; //记录每次字符串的长度
        int max=0; //记录最大字符串的长度
        for(int i=0;i<n;i++){
            for(int j=i+1;j<=n;j++){
              String s=A.substring(i,j);//通过for截取出所有可能出现的字符串
              if(isPalindromic(s)){//进行判断:2步骤
                count=s.length();
                 if(max<count){ //进行判断:3步骤
                   max=count;
                 }
               }
            }
        }
        return max;
    }
   public static boolean isPalindromic(String s) {
        int i = 0;
        int j = s.length() - 1;
        while (i <= j) {
            //取出新得到的字符串挨个字符进行比较
            if (s.charAt(i) != s.charAt(j)) {
                return false;
            }
            i++;
            j--;
        }
        return true;
    }
}
————————————————
版权声明:本文为CSDN博主「峰回路转」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_44840148/article/details/105123450

发表于 2020-03-26 17:30:32 回复(0)
class Solution {
public:
    int getLongestPalindrome(string str, int n) {
        int max=0;
        string newstr;
        for(char c:str){
            newstr+="#";
            newstr+=c;
        }
        newstr+="#";
        for(int i=0;i<2*n+1;i++){
            for(int len=0;;len++){
                if(newstr[i-len]!=newstr[i+len]||i-len<0||i+len>=2*n+1){
                    break;
                }
                if(max<len*2+1){
                    max=len*2+1;
                }
            }
        }
        return max/2;
    }
};
没用动态规划,从中心找回文,避免考虑奇偶就在每个字符中间及首位加了#使回文串必为奇数,返回的长度除以2就行了,时间复杂度大概O(n^2),主要容易理解
编辑于 2020-03-22 20:10:23 回复(0)
import java.util.*;

public class Solution {
    public int getLongestPalindrome(String A, int n) {
        // write code here
        String str=A;
        int len=str.length();
        int[][] dp=new int[len][len];
        int ans=1;
        for(int i=0;i<len;i++){
            dp[i][i]=1;
            if(i<len-1){
                if(str.charAt(i)==str.charAt(i+1)){
                    dp[i][i+1]=1;
                    ans=2;
                }
            }
        }
        for(int L=3;L<=len;L++){
            for(int i=0;i+L-1<len;i++){
                int j=i+L-1;
                if(str.charAt(i)==str.charAt(j) && dp[i+1][j-1]==1){
                    dp[i][j]=1;
                    ans=L;
                }
            }
        }
        return ans;
    }
}

发表于 2018-10-12 18:27:17 回复(0)
//尺取法
//设定left和right,left从0开始,right从left+ans 开始,ans初始化为1. 对整个字符串进行遍历
//首先是 定住left 然后找 right处和left处字符相同,然后判断 这里是不是一个回文
//如果是,可以直接替换,因为每一次的right的起始位置一定是从left加上最大长度ans之后的位置开始
//终止条件也好扣
class Solution {
public:
    int getLongestPalindrome(string A, int n) {
        int left = 0, right = 0;
        int ans = 1;
        for (left = 0; left + ans < n; left++) {
            for (right = left + ans; right < n; right++) {
                if (A[right] == A[left]) {
                    if (is_reverse(left, right, A)) {
                        ans = right - left + 1;
                    }
                }
            }
        }
        return ans;
    }
    bool is_reverse(int left, int right, string A) {
        bool is_ok = true;
        while (left <= right) {
            if (A[left] != A[right]) {
                is_ok = false;
                break;
            }
            left++;
            right--;
        }
        return is_ok;
    }
};

发表于 2018-09-23 14:46:56 回复(1)
import java.util.*;

public class Solution {
    public int getLongestPalindrome(String A, int n) {
        // write code here
        char[] ar = A.toCharArray();
        Stack<Integer> stack = new Stack<Integer>();
        for(int i = 0; i < ar.length; i++){
            for(int j = 0; j < ar.length; j++){
                if(ar[i] == ar[j] && i - j <= 2 && i != j){
                    stack.push(i);
                }
                    
            }
        }
        int max_len = 0;
        while(!stack.empty()){
        int center = stack.pop();
        int tmp1 = 0,tmp2 = 0,len = 0,left_same = 0,right_same = 0;
        int ii = center-1;
        while(ii >= 0 && ar[center] == ar[ii]){
            left_same++;
            ii--;
        }
        ii = center + 1;
        while(ii<ar.length && ar[center] == ar[ii]){
            right_same++;
            ii++;
        }
        if(left_same == right_same && left_same != 0){
            tmp1 = center + 1;
            tmp2 = center - 1;
            len++;
        }
        else if(left_same - right_same == 1){
            tmp1 = center;
            tmp2 = center-1;
        }
        else if(left_same == 0 && center - 2 >= 0 && ar[center] == ar[center - 2]){
            tmp1 = center;
            tmp2 = center - 2;
            len++;
        }
        else continue;
        while(tmp1 < ar.length && tmp2 >= 0 && ar[tmp1] == ar[tmp2]){
            len+=2;
            tmp1++;
            tmp2--;
        }
        if(max_len < len)max_len = len;
        }
        return max_len;
    }
}
彩机我写了五十多行终于写出来了,彩机我不讲思路了,肯定想麻烦了
发表于 2018-08-19 21:54:32 回复(2)
第一次学动态规划,献丑了各位

#include<stdio.h>

#include<iostream>

#include<string>

#include<string.h>

#include<algorithm>

using namespace std;

int main()

{

    string input;

    int N;

    cin>>input;

    //cin>>N;

    int dp[101][101];

    int result=1;

    for(int i=0;i<input.size();i++)

    {

        dp[i][i] = 1;

        if(i==input.size()-1)

            continue;

        if(input[i]!=input[i+1])

        {

            dp[i][i+1] = 0;

        }else

        {

            dp[i][i+1]= 2;

            result = 2;

        }

    }

    for(int i=3;i<=input.size();i++)

    {

        for(int j=0;j<input.size();j++)

        {

            int left = j;

            int right = i+j-1;

            if(right>input.size()-1)

                continue;

            if(input[left]!=input[right])

                dp[left][right]=0;

            else

            {

                if(dp[left+1][right-1]!=0)

                {

                    dp[left][right] = dp[left+1][right-1]+2;

                    result = max(result,dp[left][right]);

                }

            }

        }

    }

    cout<<result<<endl;

    

    return 0;

}


发表于 2018-03-11 22:14:47 回复(0)