算法题之最大回文子串

题目描述
对于一个字符串,请设计一个高效算法,计算其中最长回文子串的长度。
给定字符串A以及它的长度n,请返回最长回文子串的长度。

测试样例:
"abc1234321ab",12

返回:7

 

1. 普通轮询(运行时间80ms):

class Palindrome {
public:
    bool isHuiWen(string A, int n){
        int k = n / 2;
        for (int i = 0; i < k; ++i)
        {
            if (A.at(i) != A.at(n - 1 - i))
                return false;
        }
        return true;
    }

    int getLongestPalindrome(string A, int n) {
        // write code here
        int maxlen = 0;
        for (int i = 0; i< n; i++){
            for (int j = i + 1; j <= n; j++){
                //两层循环遍历出所有的子串,并且逐一判断是否是回文
                if (isHuiWen(A.substr(i, j-i), j - i)){
                    if (j - i>maxlen)
                        maxlen = j - i;
                }
            }
        }
        return maxlen;
    }
};

 

附:Leetcode上一个不错的递归解法:

#include <iostream>

using namespace std;

int lps(char* str, int i, int j)
{
    //只有一个元素,长度为1
    if (i == j)
        return 1;
    //只计算序列str[i...j]
    if (i > j)
        return 0;

    //如果首尾相同
    if (str[i] == str[j])
        return lps(str, i+1, j-1) + 2;
    //如果首尾不同
    return max(lps(str, i, j-1), lps(str, i+1, j));
}


int main()
{
    char* str = "AABACACBA";
    cout << lps(str, 0, strlen(str)-1) << endl;
    return 0;
}

 

 

2. 动态规划(运行时间40ms):

import java.util.*;
 
public class Palindrome {
    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] = len;
                    max = 2;
                    continue;
                }
                if (a[i] == a[j] && dp[i + 1][j - 1] != 0) {
                    dp[i][j] = len;
                    max = len;
                }
            }
        }
        return max;
    }
}

 

另一种解法:

//动态规划求解最长回文子序列,时间复杂度为O(n^2)  
int lpsDp(char *str, int n)  
{  
    int dp[n+1][n+1], tmp;  
    memset(dp, 0, sizeof(dp));  
    for (int i = 0; i < n; ++i)  dp[i][i] = 1;  

    for (int i = 1; i < n; ++i)  
    {  
        tmp = 0;  
        //考虑所有连续的长度为i+1的子串,str[j....j+i]  
        for (int j = 0; j + i < n; j++)  
        {  
            //如果首尾相同  
            if (str[j] == str[j + i])  
                tmp = dp[j + 1][j + i - 1] + 2;  
            //如果首尾不同  
            else   
                tmp = max(dp[j + 1][j + i], dp[j][j + i - 1]);  
            dp[j][j + i] = tmp;  
        }  
    }  
    return dp[0][n - 1]; //返回字符串str[0...n-1]的最长回文子序列长度  }

 

 

  

3. Manacher解法(时间复杂度O(n),运行时间<1ms):

class Palindrome {
public:
    int getLongestPalindrome(string A, int n) {
         
        int max = 1;
        for (int i = 0; i < n; i++)
        {
            int num = 1;
            for (int left = i - 1, right = i + 1; left >= 0 && right < n; left--, right++)
            {
                if (A[left] == A[right])
                {
                    num += 2;
                }
                else
                {
                    break;
                }
            }
            if (max < num)
            {
                max = num;
            }
         
        }
        for (int i = 0; i < n; i++)
        {
            int num = 0;
            for (int left = i, right = i + 1; left >= 0 && right < n; left--, right++)
            {
                if (A[left] == A[right])
                {
                    num += 2;
                }
                else
                {
                    break;
                }
            }
            if (max < num)
            {
                max = num;
            }
        }
        return max;
         
    }
};

  

posted @ 2017-04-20 19:01  蓝鲸王子  阅读(322)  评论(0编辑  收藏  举报