Son dynamic programming problem solving sequence of the template

The problem is common subsequence algorithm problem, but not a good solution.

First, the sequence is itself a relatively substring sub-array more difficult, because the former is not continuous sequence, the latter two are continuous, even if you will not necessarily exhaustive, let alone solve the problem related algorithms .

Moreover, the subsequence problem is most likely related to two strings, such as earlier, "the longest common subsequence" without some experience in dealing with, really is not easy to get out. So this came Grilled routine subsequence problem of a steak, in fact, there are two templates related to this issue as long as two ideas think, shoo.

Typically, such a problem is to let you find the longest sequence , because the shortest sequence is a character thing, nothing to ask. When it comes to the sequence and the most value, it almost certainly examine the dynamic programming techniques are generally time complexity O (the n-^ 2) .

The reason is simple, you think about a string of number sequences possible? At least it is exponential, in this case, not dynamic programming skills, want how was that?

Since the use of dynamic programming, it would have to define dp array, looking for state transition relationship. We say that the two ideas template is defined ideas dp array. Different problems may require different dp array definition to resolve.

One, two ideas

1, the first thought template is a one-dimensional array of dp :

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] = 最值(dp[i], dp[j] + ...)
    }
}

For example, we wrote the "longest increasing subsequence" is defined in this idea dp arrays are:

In the sub-array array[0..i], the length of subsequence Required (longest increasing sequence) isdp[i] .

Why longest increasing subsequence need this line of thinking it? Previously he said very clearly, because this accord induction, can be found in the relationship between the state transition here is not specifically launched.

2, the second idea template is a two-dimensional array dp :

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] = 最值(...)
    }
}

This line of thinking to use relatively more, especially involving sequences of two strings / arrays, such as previously talked about "the longest common subsequence." This idea of ​​the meaning dp array is divided into "involves only a string" and "involves two strings" in both cases.

2.1 two strings involves / an array (such as the longest common subsequence), meaning dp array as follows:

In sub-arrays arr1[0..i]and sub-arrays arr2[0..j], the sub-sequences (the longest common subsequence) Desired lengthdp[i][j] .

2.2 relates to a string / an array (such as talk herein longest palindromic sequence), meaning dp array as follows:

In the sub-array array[i..j], the sub-sequence length (longest palindromic sequence) for our requirementsdp[i][j] .

The first case can refer to these two old text: "edit distance", "common subsequence"

Here's longest palindromic sequence by this problem, Detailed look at the second case how to use dynamic programming.

Second, the longest palindromic sequence

Prior to solve the "longest palindrome substring" problem, this time to enhance the degree of difficulty, find the length of the longest palindromic sequence of:

We say that this issue is the definition of dp arrays: sub-string s[i..j], the length of the longest palindromic sequencedp[i][j] . Be sure to remember this definition to understand algorithms.

Why this question should be defined in such a two-dimensional array dp it? We previously mentioned several times, looking for state transition requires inductive thinking, bluntly, is how out of the known results unknown part , this definition is easy to generalize, easy to find the relationship between the state transition.

Specifically, if we want to ask dp[i][j], if you know a child problem dp[i+1][j-1]outcomes ( s[i+1..j-1]the longest palindromic sequence of sub-length), if you can find a way to calculate the dp[i][j]value of ( s[i..j]the longest palindromic sequence of sub-length) it?

can! It depends s[i]and s[j]characters:

If Talia equal , then add Talia s[i+1..j-1]longest palindromic sequence is the child of s[i..j]the longest palindromic sequence:

If not equal Talia , Talia instructions can not simultaneously appear in the s[i..j]longest palindromic sequence in, so Talia are added s[i+1..j-1]in, to see which produces the substring longer palindromic sequences can be:

In both cases the code is written like this:

if (s[i] == s[j])
    // 它俩一定在最长回文子序列中
    dp[i][j] = dp[i + 1][j - 1] + 2;
else
    // s[i+1..j] 和 s[i..j-1] 谁的回文子序列更长?
    dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);

So far, the state transition equation to write out, by definition dp array, we require is dp[0][n - 1], that is, the entire slength of the longest palindromic sequence.

Third, code implementation

First, be clear about base case, if there is only one character, by far the longest palindromic sequence length is 1, that is dp[i][j] = 1 (i == j).

Because icertainly less jso for those i > jpositions, there is simply not what the sequence should be initialized to zero.

In addition, take a look at just written state transition equation, I would like to ask dp[i][j]you need to know dp[i+1][j-1], dp[i+1][j], dp[i][j-1]the three positions; take a look at our base case determined, after fill dp array like this:

To ensure each calculation dp[i][j], the position of the lower left and right directions have been calculated, only the anti-traverse or obliquely traversing :

I chose the opposite of traversal code is as follows:

int longestPalindromeSubseq(string s) {
    int n = s.size();
    // dp 数组全部初始化为 0
    vector<vector<int>> dp(n, vector<int>(n, 0));
    // base case
    for (int i = 0; i < n; i++)
        dp[i][i] = 1;
    // 反着遍历保证正确的状态转移
    for (int i = n - 1; i >= 0; i--) {
        for (int j = i + 1; j < n; j++) {
            // 状态转移方程
            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]);
        }
    }
    // 整个 s 的最长回文子串长度
    return dp[0][n - 1];
}

So far, the longest palindromic sequence of problems to solve.

我最近精心制作了一份电子书《labuladong的算法小抄》,分为【动态规划】【数据结构】【算法思维】【高频面试】四个章节,共 60 多篇原创文章,绝对精品!限时开放下载,在我的公众号 labuladong 后台回复关键词【pdf】即可免费下载!

目录

欢迎关注我的公众号 labuladong,技术公众号的清流,坚持原创,致力于把问题讲清楚!

labuladong

Guess you like

Origin www.cnblogs.com/labuladong/p/12320381.html