Python 最长回文子串自顶向下动态规划

Python 最长回文子串自顶向下动态规划,python,dynamic-programming,palindrome,memoization,Python,Dynamic Programming,Palindrome,Memoization,下面是使用自底向上动态规划查找给定字符串s的最长回文子字符串的算法。因此,该算法探索所有可能的长度j子字符串,并检查它是否是1到n中j的有效回文。由此产生的时间和空间复杂性是O(n^2) def最长回文: n=长(s) 如果n=j){ 返回false; } 如果(T[i][j]=-1){ if(str[i]==str[j]){ T[i][j]=isPalindrome(str,startIdx+1,stopIdx-1,T); } 否则{ T[i][j]=0; } } 返回值(T[i][j]==1

下面是使用自底向上动态规划查找给定字符串
s
的最长回文子字符串的算法。因此,该算法探索所有可能的长度
j
子字符串,并检查它是否是1到n中
j
的有效回文。由此产生的时间和空间复杂性是
O(n^2)

def最长回文:
n=长(s)
如果n<2:
返回s
P=[[范围内(n)为假]范围内(n)]
最长=s[0]
#j是回文的长度
对于范围(1,n+1)内的j:
对于范围内的i(n-j+1):
#如果长度小于3,则检查s[i]==s[i+j-1]就足够了
P[i][i+j-1]=s[i]==s[i+j-1]和(j<3或P[i+1][i+j-2])
如果P[i][i+j-1]和j>len(最长):
最长=s[i:i+j]
回程最长
我试图用自上而下的方法实现相同的算法,并进行记忆

问题: 是否可以将此算法转换为自顶向下方法


关于最长回文子串有很多问题,但他们大多使用这种自下而上的方法。中的答案似乎与我的想法最为接近。但答案似乎是使用了与此不同的算法(而且要慢得多)。

以下是我的递归解决方案: 从i=0开始,j=最大长度 如果(i,j)是回文:那么最大子串长度是j-1。 否则用(i+1,j)和(i,j-1)进行递归,取两者之间的最大值。 代码将解释更多。 代码是用Java编写的,但我希望它能给出如何实现它的想法@zcadqe希望了解如何采用自上而下的方法实施。我给出了这个想法,作为奖励,我还提供了java代码,以便更好地理解。任何了解python的人都可以轻松地转换代码

public class LongestPalindromeSubstringWithSubStr {
static String str;
static int maxLen;
static int startLen;
static int endLen;
static int dp[][];// 0: not calculaed. 1: from index i to j is palindrome

static boolean isPal(int i, int j) {
    if (dp[i][j] != 0) {
        System.out.println("Res found for i:" + i + " j: " + j);
        return (dp[i][j] == 1);
    }
    if (i == j) {
        dp[i][j] = 1;
        return true;
    }
    if (i + 1 == j) {// len 2
        if (str.charAt(i) == str.charAt(j)) {
            dp[i][j] = 1;
            return true;
        }
        dp[i][j] = -1;
        return false;
    }
    if (str.charAt(i) == str.charAt(j)) {
        boolean res = isPal(i + 1, j - 1);
        dp[i][j] = (res) ? 1 : 0;
        return res;
    }
    dp[i][j] = 0;
    return false;
}

// update if whole string from i to j is palindrome
static void longestPalCalc(int i, int j) {
    if (isPal(i, j)) {
        if (j - i + 1 > maxLen) {// update res
            maxLen = j - i + 1;
            startLen = i;
            endLen = j;
        }
    } else {
        longestPalCalc(i + 1, j);
        longestPalCalc(i, j - 1);
    }
}

public static void main(String[] args) {
    str = "abadbbda";
    dp = new int[str.length()][str.length()];
    longestPalCalc(0, str.length() - 1);
    System.out.println("Longest: " + maxLen);
    System.out.println(str.subSequence(startLen, endLen + 1));
}

}以下是我的递归解决方案: 从i=0开始,j=最大长度 如果(i,j)是回文:那么最大子串长度是j-1。 否则用(i+1,j)和(i,j-1)进行递归,取两者之间的最大值。 代码将解释更多。 代码是用Java编写的,但我希望它能给出如何实现它的想法@zcadqe希望了解如何采用自上而下的方法实施。我给出了这个想法,作为奖励,我还提供了java代码,以便更好地理解。任何了解python的人都可以轻松地转换代码

public class LongestPalindromeSubstringWithSubStr {
static String str;
static int maxLen;
static int startLen;
static int endLen;
static int dp[][];// 0: not calculaed. 1: from index i to j is palindrome

static boolean isPal(int i, int j) {
    if (dp[i][j] != 0) {
        System.out.println("Res found for i:" + i + " j: " + j);
        return (dp[i][j] == 1);
    }
    if (i == j) {
        dp[i][j] = 1;
        return true;
    }
    if (i + 1 == j) {// len 2
        if (str.charAt(i) == str.charAt(j)) {
            dp[i][j] = 1;
            return true;
        }
        dp[i][j] = -1;
        return false;
    }
    if (str.charAt(i) == str.charAt(j)) {
        boolean res = isPal(i + 1, j - 1);
        dp[i][j] = (res) ? 1 : 0;
        return res;
    }
    dp[i][j] = 0;
    return false;
}

// update if whole string from i to j is palindrome
static void longestPalCalc(int i, int j) {
    if (isPal(i, j)) {
        if (j - i + 1 > maxLen) {// update res
            maxLen = j - i + 1;
            startLen = i;
            endLen = j;
        }
    } else {
        longestPalCalc(i + 1, j);
        longestPalCalc(i, j - 1);
    }
}

public static void main(String[] args) {
    str = "abadbbda";
    dp = new int[str.length()][str.length()];
    longestPalCalc(0, str.length() - 1);
    System.out.println("Longest: " + maxLen);
    System.out.println(str.subSequence(startLen, endLen + 1));
}
}
#包括
#包括
#包括
使用名称空间std;
bool isPalindrome(字符串str、int startIdx、int stopIdx、vector&T){
const int i=startIdx;
const int j=stopIdx-1;
如果(i==(j+1)){
返回true;
}
如果(i>=j){
返回false;
}
如果(T[i][j]=-1){
if(str[i]==str[j]){
T[i][j]=isPalindrome(str,startIdx+1,stopIdx-1,T);
}
否则{
T[i][j]=0;
}
}
返回值(T[i][j]==1);
}
string getLongestStr(string str、int startIdx、int stopIdx、vector&T){
if(isPalindrome(str、startIdx、stopIdx、T)){
返回str.substr(startIdx,(stopIdx-startIdx));
}
否则{
字符串str1=getLongestStr(str,startIdx+1,stopIdx,T);
字符串str2=getLongestStr(str,startIdx,stopIdx-1,T);
返回str1.size()>str2.size()?str1:str2;
}
返回“”;
}
字符串getLongestStr(字符串str){
常量int N=str.size();
向量T(N,向量(N,-1));
返回getLongestStr(str,0,N,T);
}
int main(){
string str=“forgekskeegfor”;
//string str=“Geeks”;
不能包含
#包括
#包括
使用名称空间std;
bool isPalindrome(字符串str、int startIdx、int stopIdx、vector&T){
const int i=startIdx;
const int j=stopIdx-1;
如果(i==(j+1)){
返回true;
}
如果(i>=j){
返回false;
}
如果(T[i][j]=-1){
if(str[i]==str[j]){
T[i][j]=isPalindrome(str,startIdx+1,stopIdx-1,T);
}
否则{
T[i][j]=0;
}
}
返回值(T[i][j]==1);
}
string getLongestStr(string str、int startIdx、int stopIdx、vector&T){
if(isPalindrome(str、startIdx、stopIdx、T)){
返回str.substr(startIdx,(stopIdx-startIdx));
}
否则{
字符串str1=getLongestStr(str,startIdx+1,stopIdx,T);
字符串str2=getLongestStr(str,startIdx,stopIdx-1,T);
返回str1.size()>str2.size()?str1:str2;
}
返回“”;
}
字符串getLongestStr(字符串str){
常量int N=str.size();
向量T(N,向量(N,-1));
返回getLongestStr(str,0,N,T);
}
int main(){
string str=“forgekskeegfor”;
//string str=“Geeks”;

问题是关于Python的,这是Java。那些给出负面评价的人:代码是Java的,但我希望它能给出如何实现它的想法。@zcadqe想知道如何用自上而下的方法实现。我给出了想法,作为奖励,还提供了Java代码,以便于更好地理解。任何了解Python的人都可以轻松地与我们合作重新编写代码!@BramVanroy:问题不在于python。问题是:“是否有可能将此算法转换为自顶向下的方法?”阅读标签。问题是关于Python的。如果你对Java代码很不满意,那么请忽略Java部分。有4个标签,我已经回答了其中的3个,即动态编程、回文、备忘录。我相信重点是算法,代码语言根本不重要。问题是关于Python的,这是Java。那些ve负面评价:代码是用Java编写的,但我希望它能给出如何实现它的想法。@zcadqe想知道如何用自上而下的方法实现它。我给出了这个想法,作为奖励,我还提供了Java代码,以便更好地理解。任何懂python的人都可以轻松地转换代码!@BramVanroy:问题不在于python.问题是:“是否有可能将此算法转换为自顶向下的方法?”
#include<iostream>
#include<string>
#include<vector>

using namespace std;

bool isPalindrome(string str, int startIdx, int stopIdx, vector<vector<int>>& T) {
    const int i = startIdx;
    const int j = stopIdx - 1;

    if (i == (j + 1)) {
        return true;
    }
    if (i >= j) {
        return false;
    }
    if (T[i][j] == -1) {
        if (str[i] == str[j]) {
            T[i][j] = isPalindrome(str, startIdx + 1, stopIdx - 1, T);
        }
        else {
            T[i][j] = 0;
        }
    }
    return (T[i][j] == 1);
}

string getLongestStr(string str, int startIdx, int stopIdx, vector<vector<int>>& T) {
    if (isPalindrome(str, startIdx, stopIdx, T)) {
        return str.substr(startIdx, (stopIdx - startIdx));
    }
    else {
        string str1 = getLongestStr(str, startIdx + 1, stopIdx, T);
        string str2 = getLongestStr(str, startIdx, stopIdx - 1, T);
        return str1.size() > str2.size() ? str1 : str2;
    }
    return "";
}

string getLongestStr(string str) {
    const int N = str.size();
    vector<vector<int>> T(N, vector<int>(N, -1));
    return getLongestStr(str, 0, N, T);
}

int main() {
    string str = "forgeeksskeegfor";
    //string str = "Geeks";
    
    cout << getLongestStr(str) << endl;
    return 0;
}