当前位置:网站首页>Problem solving templates for subsequence problems in dynamic programming

Problem solving templates for subsequence problems in dynamic programming

2020-11-08 19:51:00 labuladong,

After reading this article , You can go and get the following questions :

516. The longest palindrome subsequence

-----------

Subsequence problem is a common algorithm problem , And it's not easy to solve .

First , Subsequence problem itself is relative to substring 、 Subarrays are more difficult , Because the former is a discontinuous sequence , The latter two are continuous , Even if you are poor, you will not , Let alone solve the related algorithm problem .

and , The subsequence problem is likely to involve two strings , For example 「 Longest common subsequence 」, If there is no certain experience in handling , It's really not easy to come up with . Therefore, this paper will take a look at the subsequence problem , There are actually two templates , If you think about these two ways of thinking about the relevant problems , as sure as a gun .

Generally speaking , All these questions are for you to ask for one The longest subsequence , Because the shortest subsequence is a character , There's nothing to ask . Once the sub sequence and the maximum value are involved , That's almost certain , It is dynamic planning techniques , Time complexity is generally O(n^2).

The reason is simple , You think about a string , How many possibilities are its subsequences ? At least it's exponential , In this case , Don't use dynamic planning techniques , What else do you want to do ?

Since we have to use dynamic programming , Then define dp Array , Find a state transition relationship . Two ideas we're talking about , Namely dp How to define arrays . Different questions may need different dp Array definition to solve .

One 、 Two ways of thinking

1、 The first idea template is a one-dimensional dp Array

int n = array.length;
int[] dp = new int[n];

for (int i = 1; i < n; i++) {
    for (int j = 0; j < i; j++) {
        dp[i] =  The most value (dp[i], dp[j] + ...)
    }
}

Take an example we wrote 「 The longest increasing subsequence 」, In this way of thinking dp The definition of an array is :

In subarray array[0..i] in , We need subsequences ( The longest increasing subsequence ) Is the length of the dp[i].

Why the longest increaser needs this kind of thinking ? The previous article is very clear , Because it is in line with induction , You can find the relationship of state transfer , It's not going to be specific here .

2、 The second idea template is a two-dimensional dp Array

int n = arr.length;
int[][] dp = new dp[n][n];

for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
        if (arr[i] == arr[j]) 
            dp[i][j] = dp[i][j] + ...
        else
            dp[i][j] =  The most value (...)
    }
}

This kind of thinking is used relatively more , Especially when it comes to two strings / Subsequences of arrays , For example, as mentioned above 「 Longest common subsequence 」. In this idea dp The meaning of array is divided into 「 Only one string involved 」 and 「 It involves two strings 」 Two cases .

PS: I've seriously written about 100 Multiple original articles , Hand brush 200 Daoli is the subject , All published in labuladong A copy of the algorithm , Continuous updating . Recommended collection , Write the title in the order of my article , Master all kinds of algorithm set, then put into the sea of questions, like fish .

2.1 It involves two strings / Array time ( For example, the longest common subsequence ),dp The meaning of array is as follows :

In subarray arr1[0..i] And subarray arr2[0..j] in , We need subsequences ( Longest common subsequence ) The length is dp[i][j].

2.2 Only one string involved / Array time ( For example, the longest palindrome subsequence in this paper ),dp The meaning of array is as follows :

In subarray array[i..j] in , We need subsequences ( The longest palindrome subsequence ) The length of is dp[i][j].

In the first case, we can refer to these two old articles :「 Edit distance 」「 Common subsequence 」

Let's borrow the longest palindrome subsequence , Explain how to use dynamic programming in the second case .

Two 、 The longest palindrome subsequence

It was solved before 「 Longest text substring 」 The problem of , This time it's more difficult , Find the length of the longest palindrome subsequence :

We say the problem is right dp The definition of an array is : In substring s[i..j] in , The longest length of the palindrome subsequence is dp[i][j]. You have to remember this definition to understand algorithms .

Why does this problem define two-dimensional dp Array? ? We have mentioned many times before that , Finding state transfer requires inductive thinking , To put it bluntly, it is how to deduce the unknown from known results , This definition is easy to generalize , It's easy to find state transfer relationships .

say concretely , If we want to ask for dp[i][j], Suppose you know the sub problem dp[i+1][j-1] Result (s[i+1..j-1] The length of the longest palindrome subsequence in ), Can you figure out how to figure out dp[i][j] Value (s[i..j] in , The length of the longest palindrome subsequence ) Well ?

Sure ! It depends. s[i] and s[j] The characters of :

If they are equal , So it's two plus s[i+1..j-1] The longest sequence of palindrome in is s[i..j] The longest palindrome subsequence of :

If it's not equal , It's two of them It can't be at the same time Appear in the s[i..j] In the longest palindrome subsequence of , So take them both , respectively, Join in s[i+1..j-1] in , See which substring produces a longer palindrome sequence :

The above two cases of code is like this :

if (s[i] == s[j])
    //  They must be in the longest palindrome subsequence 
    dp[i][j] = dp[i + 1][j - 1] + 2;
else
    // s[i+1..j]  and  s[i..j-1]  Whose palindrome subsequence is longer ?
    dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);

thus , The equation of state transfer is written out , according to dp Definition of array , What we want is dp[0][n - 1], That is the whole s The length of the longest palindrome subsequence of .

3、 ... and 、 Code implementation

First, make it clear base case, If there is only one character , Obviously, the longest palindrome subsequence length is 1, That is to say dp[i][j] = 1 (i == j).

because i It must be less than or equal to j, So for those i > j The location of , There is no substequence at all , It should be initialized to 0.

in addition , Look at the state transition equation we just wrote , Want to ask for dp[i][j] Need to know dp[i+1][j-1],dp[i+1][j],dp[i][j-1] These three positions ; And then look at what we're sure about base case, fill dp The array is followed by this :

To ensure that every calculation dp[i][j], The position of the lower left and the right has been calculated , You can only traverse sideways or backwards

I choose to traverse backwards , The code is as follows :

int longestPalindromeSubseq(string s) {
    int n = s.size();
    // dp  The array is all initialized to  0
    vector<vector<int>> dp(n, vector<int>(n, 0));
    // base case
    for (int i = 0; i < n; i++)
        dp[i][i] = 1;
    //  Reverse traversal ensures correct state transition 
    for (int i = n - 1; i >= 0; i--) {
        for (int j = i + 1; j < n; j++) {
            //  State transition equation 
            if (s[i] == s[j])
                dp[i][j] = dp[i + 1][j - 1] + 2;
            else
                dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);
        }
    }
    //  Whole  s  The longest palindrome substring length of 
    return dp[0][n - 1];
}

thus , The problem of the longest palindrome subsequence is solved .

_____________

my Online e-books Yes 100 Original articles , Hands with brushes 200 Daoli is the subject , Recommended collection ! Corresponding GitHub Algorithm Repository We've got it 70k star, Welcome to mark star !

版权声明
本文为[labuladong,]所创,转载请带上原文链接,感谢