Common questions about palindrome

1. The longest palindrome substring

This question should be explained carefully. I have done it several times, and then forgot after a period of time. So to sum it up, take it out when you forget it, and use two more understandable methods to do it.

First go to the dynamic programming code

class Solution:
    def longestPalindrome(self, s: str) -> str:
        if not s:
            return ''
        n = len(s)
        maxlen = 0
        res = 0
        dp = [[False for _ in range(n)]for _ in range(n)]
        for j in range(n):
            for i in range(j+1):
                dp[i][j] = s[i]==s[j] and (j-i<=2 or dp[i+1][j-1])
                if dp[i][j]:
                    if j-i+1>maxlen:
                        maxlen = j-i+1
                        res = s[i:j+1]
        return res

Take s ='babad' as an example, j keeps going backwards, i is from 0 to j, and constantly judges, so the two-layer for loop is written as in the code, when j=4, i goes from 0 to 4. Then go to find the longest palindrome

Of course, there are other ways to write the two-layer for loop, the picture comes from the source

image.png

dp[i][j] indicates whether s[i] and s[j] are equal. If they are equal, and dp[i+1][j-1] is also equal, it means that the previous is a palindrome substring, and then add Go on these two now. So dp[i][j] = s[j] == s[j] && dp[i+1][j-1], but looking at the code, there is also an option j-i <=2 for the following reasons:

s ='babad', when i=0, j=2, ji=2, and s[j] == s[j], only one element a in the middle is definitely a palindrome, so there is no need to judge dp [i+1][j-1], it is directly right.

And j-i <= 2 should be written before dp[i+1][j-1], otherwise an error will be reported, because when i=1, j=2, if you write dp[i+1][j- 1], then i becomes 2 and j becomes 1, which is wrong from the analysis just now, because j is constantly going backwards, and i is from 0 to j, i exceeds j, so No way. The other parts are better to understand, so I won’t explain

The second method:

class Solution:
    def __init__(self):
        self.res = ''
    def longestPalindrome(self, s: str) -> str:
        if not s:
            return ''
        for i in range(len(s)):
            self.helper(s,i,i)
            self.helper(s,i,i+1)
        return self.res
    def helper(self,s,left,right):
        while left>=0 and right<len(s) and s[left]==s[right]:
            left-=1
            right+=1
        cur = s[left+1:right]
        if len(cur)>len(self.res):
            self.res = cur 

This method adopts the central diffusion method

Spread from the middle to both sides, but the length of the string may be odd or even, so write it twice directly, the result is the same

2. The longest palindrome subsequence

Code first

class Solution:
    def longestPalindromeSubseq(self, s: str) -> int:
        if not s:
            return 0
        n = len(s)
        dp = [[0 for _ in range(n)]for _ in range(n)]
        for i in range(n):
            dp[i][i] = 1
        for i in range(n-1,-1,-1):
            for j in range(i+1,n):
                if s[i]==s[j]:
                    dp[i][j] = dp[i+1][j-1]+2
                else:
                    dp[i][j] = max(dp[i][j-1],dp[i+1][j])
        return dp[0][n-1]

The core code is the following, in fact, it is easier to understand. If the letters at both ends are the same, add 2 to the length, otherwise it depends on the length of the substrings on both sides and take the longest one.

if s[i]==s[j]:
    dp[i][j] = dp[i+1][j-1]+2          
else:
    dp[i][j] = max(dp[i][j-1],dp[i+1][j])
                   

For two for loops, the first for loop sets the position of i from the back. If the string is "bbbab", when i points to the second position, j starts from the third and goes backwards and sequentially Compare the letter at the i-th position

Guess you like

Origin blog.csdn.net/Matrix_cc/article/details/108691638