简体   繁体   English

最长回文 substring 自顶向下递归方法

[英]Longest palindromic substring top down recursive approach

I am trying to solve Longest palindromic substring on Leetcode.我正在尝试解决 Leetcode 上最长的回文substring。 I a aware of solutions for this problem like expand around center or dynamic programming bottom up approach .我知道这个问题的解决方案,比如围绕中心展开或动态编程自下而上的方法 For purely educational purposes I wanted to solve this in top down recursive manner.出于纯粹的教育目的,我想以自上而下的递归方式解决这个问题。 I am trying to find solution similar to what is described here or here .我正在尝试找到类似于此处此处描述的解决方案。 (problem is slighly different). (问题略有不同)。 I have this function:我有这个 function:

private (int Start, int End) Longest(string s, int i, int j)

which takes string + start and end position of search.这需要字符串 + 开始和结束 position 搜索。 Tuple which is return is start and end of longest palindrom.返回的元组是最长回文的开始和结束。 I am trying to split into these cases:我试图分成这些情况:

  1. if s[i] == s[j] investigate Longest(s, i+1, j-1) if s[i] == s[j] 调查 Longest(s, i+1, j-1)
  2. Investigate Longest(s, i+1, j)调查最长(s, i+1, j)
  3. Investigate Longest(s, i, j - 1)调查最长(s, i, j - 1)
  4. Return longest (max difference between returned start and end) from these three从这三个中返回最长(返回的开始和结束之间的最大差异)

Of course I am using Dictionary with tuple (int, int) as key (values of i and j) to remember all computed results to not compute them again.当然,我使用以元组 (int, int) 作为键(i 和 j 的值)的字典来记住所有计算结果,以便不再计算它们。

Full code is below but it is very messy after few several iterations when I was trying to fix algorithm.完整的代码如下,但是当我尝试修复算法时,经过几次迭代后它非常混乱。 I believe concreate code is not very important.我相信创建代码不是很重要。

Code seems to be returning correct results but fail on Time Limit Exceeded on Leetcode.代码似乎返回了正确的结果,但在 Leetcode 上的 Time Limit Exceeded 上失败了。 Is there correct fast recursive solution?是否有正确的快速递归解决方案? I believe there should be as DP bottom up solution exists.我相信应该存在 DP 自下而上的解决方案。

code:代码:

private readonly IDictionary<(int, int), (int, int)> _mem = new Dictionary<(int, int), (int, int)>();

private (int Start, int End) Longest(string s, int i, int j) {
    if (i >= j) {
        return (i, j);
    }

    if (_mem.TryGetValue((i, j), out var ret)) {
        return ret;
    }

    var newI = i + 1;
    var newJ = j - 1;

    ValueTuple<int, int> removingTwo;

    if (s[i] == s[j])
    {
        removingTwo = Longest(s, newI, newJ);

        if (removingTwo.Item1 == newI && removingTwo.Item2 == newJ) {
            removingTwo.Item1--;
            removingTwo.Item2++;
        }
    }
    else {
        removingTwo = (1, 0);
    }

    var removingFirst = Longest(s, newI, j);
    var removingLast = Longest(s, i, newJ);  

    var mT = removingTwo.Item2 - removingTwo.Item1;
    var mF = removingFirst.End - removingFirst.Start;
    var mL = removingLast.End - removingLast.Start;

    var max = Math.Max(mT, mF);
    max = Math.Max(max, mL);

    ValueTuple<int, int> retVal;

    if (max == mT) retVal = removingTwo;
    else if (max == mF) retVal = removingFirst;
    else retVal = removingLast;

    _mem.Add((i, j), retVal);

    return retVal;

}

Edit : working bottom-up solution (copied from geegsforgeegs ):编辑:工作自下而上的解决方案(从geegsforgeegs复制):

public string LongestPalindrome(string s) {
    if (s.Length == 0) return "";
    var table = new bool[s.Length, s.Length];
    var len = s.Length;
    for (int i = 0; i < len; i++) {
        table[i,i] = true;
    }

    var start = 0;
    var max = 1;
    for (int i = 0; i < len - 1; i++) {
        if (s[i] == s[i + 1]) {
            start = i;
            max = 2;
            table[i, i+1] = true;
        }
    }

    for (int k = 3; k <= len; ++k) { 

              // Fix the starting index 
        for (int i = 0; i < len - k + 1; ++i)  
        { 
            // Get the ending index of substring from 
            // starting index i and length k 
            int j = i + k - 1; 

            // checking for sub-string from ith index to 
            // jth index iff str.charAt(i+1) to  
            // str.charAt(j-1) is a palindrome 
            if (table[i + 1, j - 1] && s[i] == s[j]) { 
                table[i,j] = true; 

                if (k > max) { 
                    start = i; 
                    max = k; 
                } 
            } 
        } 
    } 

    return s.Substring(start, max);
}

Here's a recursive method in Python that passes the LeetCode test.这是 Python 中通过 LeetCode 测试的递归方法。 It may be that they are looking for a constant space solution.可能他们正在寻找一个恒定的空间解决方案。

f(i, k) returns (l, j) , the largest tuple of length l and its starting index, j . f(i, k)返回(l, j) ,长度为l的最大元组及其起始索引j max in this instance is looking at the first element of the returned tuple, which is l , the palindrome's length.在这种情况下, max正在查看返回元组的第一个元素,即l ,即回文的长度。

def longestPalindrome(self, s):
  def f(i, k):
    return max(
      # next iteration
      f(i - 1, 1) if k < 2 and i > 0 else (-1,-1),
      f(i - 1, 2) if k < 2 and i > 0 and s[i-1] == s[i] else (-1, -1),

      # a larger palindrome than this one
      f(i - 1, k + 2) if i > 0 and i + k < len(s) and s[i-1] == s[i + k] else (-1, -1),

      # this one
      (k, i)
    )

  (l, j) = f(len(s) - 1, 1)
  return s[j:j+l]

simple recursive solution, Not Memoization简单的递归解决方案,不是记忆

 def palandrom(A,i,j):
        if i > j: 
            return ''
        elif i == j: 
            return A[i]
    
        elif A[i] == A[j]: 
            save = A[i+1 : j]
            if save == save[::-1]:
                i = len(A) #As we know rest of string are palandrome we want to make i>j condition true 

                return (A[i] + save + A[j])
    
        left = palandrom(text,i+1,j)
        right = palandrom(text,j,j+1)
        return left if len(left) > len(right) else right
    
    print(palandrom(loiol,0,4))

The best solution to find longest possible palindrome in a string using Python使用 Python 在字符串中找到最长可能回文的最佳解决方案

inp=input("Enter a string:\n")

tmp=''
pal=[]

for i in inp:
    tmp+=i
    if tmp==tmp[::-1] and len(tmp)>1:
        pal.append(tmp)
        tmp=''

print(pal)

if len(pal)>0:
    tmp=sorted(pal,key=len)
    print(f'Longest palindrome : {tmp[-1]}')
else:
    print("No pattern found except individual letters!")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM