zoukankan      html  css  js  c++  java
  • 算法题之最大回文子串

    题目描述
    对于一个字符串,请设计一个高效算法,计算其中最长回文子串的长度。
    给定字符串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;
             
        }
    };
    

      

  • 相关阅读:
    牛客练习赛51 D题
    Educational Codeforces Round 72 (Rated for Div. 2) C题
    Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) C题
    Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) A题
    Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) A题
    Educational Codeforces Round 72 (Rated for Div. 2) B题
    Educational Codeforces Round 72 (Rated for Div. 2) A题
    《DSP using MATLAB》Problem 7.2
    《DSP using MATLAB》Problem 7.1
    《DSP using MATLAB》Problem 6.24
  • 原文地址:https://www.cnblogs.com/shixiangwan/p/6740309.html
Copyright © 2011-2022 走看看