718. Maximum Length of Repeated Subarray

write picture description here

The general meaning of the title is to find the length of the largest consecutive subsequence in the two arrays.


The problem is naturally solved by moving back, but at the beginning I thought wrongly, the code is as follows:

public int findLength2(int[] A, int[] B) {
     int[][] dp = new int[A.length][B.length];
     dp[0][0] = A[0] == B[0] ? 1 : 0;
     for (int j = 1; j < B.length; j++) {
         dp[0][j] = A[0] == B[j] ? 1 : dp[0][j - 1];
     }
     for (int i = 1; i < A.length; i++) {
         dp[i][0] = A[i] == B[0] ? 1 : dp[i - 1][0];
     }
     for (int i = 1; i < A.length; i++) {
         for (int j = 1; j < B.length; j++) {
             if (A[i]==B[j]) {
                 if (A[i-1]==B[j-1]) {
                     dp[i][j] = dp[i - 1][j - 1] + 1;
                 } else {
                     dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j]);
                     dp[i][j] = Math.max(dp[i][j], 1);
                 }
             } else {
                 dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j]);
             }
         }
     }
     return dp[A.length - 1][B.length - 1];
}

At this point, my idea is to use the auxiliary array dp, where dp[i][j]represents the maximum length value of the same continuous subsequence that exists in the twoA[0,i] sequences. B[0,j]So we have the following transition equation:

At that A[i]==B[j]time , it depends on A[i-1]==B[j-1]whether it is established,

如果相等就在 dp[i-1][j-1] 的基础上 +1,即 dp[i][j] = dp[i - 1][j - 1] + 1
如果不想等,dp[i][j] 为 dp[i][j - 1], dp[i - 1][j],1 三者中的最大值

Therefore, it has been said before that dp[i][j]represents the maximum length value in the same continuous subsequence existing in the A[0,i]and B[0,j]two sequences, and dp[i][j - 1], dp[i - 1][j]both may be 0, and the meaning of 1 means that in A[0,i]and B[0,j]in only A[i]and B[j]are equal to the two subsequences.

At that A[i]!=B[j]time , directly takedp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j])

The problem is that dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j])this logic results in dp[i][j]always being the maximum length value in the same contiguous subsequence that exists in the A[0,i]and B[0,j]two sequences, which can cause errors in some data, as follows:
write picture description here

Obviously, the meaning represented by dp[i][j] is wrong. It should not be A[0,i]the B[0,j]maximum length value in the same continuous subsequence existing in the and two sequences, but should be A[0,i]and B[0,j]The two sequences are based on A[i]and B[j]. , the length of the largest identical subsequence that can be obtained by forward comparison is:

if (A[i]==B[j]) {
    if (A[i-1]==B[j-1]) {
        dp[i][j] = dp[i - 1][j - 1] + 1;
    } else {
        dp[i][j] = 1;
    }
} else {
    dp[i][j] = 0;
}

At this time, a temporary variable is also needed to A[0,i]store B[0,j]the maximum length value in the same continuous subsequence existing in and , so that dp[i-1][j-1]the value of will not incorrectly affect dp[i][j]the value of .

public int findLength(int[] A, int[] B) {
    int[][] dp = new int[A.length][B.length];
    int maxLen = 0;
    dp[0][0] = A[0] == B[0] ? 1 : 0;
    for (int j = 1; j < B.length; j++) {
        dp[0][j] = A[0] == B[j] ? 1 : 0;
        if (maxLen<dp[0][j]) maxLen = dp[0][j];
    }
    for (int i = 1; i < A.length; i++) {
        dp[i][0] = A[i] == B[0] ? 1 : 0;
        if (maxLen<dp[i][0]) maxLen = dp[i][0];
    }
    for (int i = 1; i < A.length; i++) {
        for (int j = 1; j < B.length; j++) {
            if (A[i]==B[j]) {
                if (A[i-1]==B[j-1]) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                } else {
                    dp[i][j] = 1;
                }
            } else {
                dp[i][j] = 0;
            }
            if (maxLen<dp[i][j]) maxLen = dp[i][j];
        }
    }
    return maxLen;
}

After that, the auxiliary array can also be reduced from 2D to 1D, taking into account optimization.
In two-dimensional, both A and B are traversed from the beginning, and dp[i][j]again dp[i - 1][j - 1], so when using a one-dimensional array, you dp[k]need to rely on the unupdated dp[k-1], but when k dp[k-1]has been updated, so you need to change the angle, Therefore, A can be traversed from the end to the beginning, and the appeal problem can be solved at this time.

public int findLength(int[] A, int[] B) {
    int m=A.length,n=B.length;
    int max=0;
    int[] dp=new int[n+1];
    for(int i=m-1;i>=0;i--){//从后遍历数组 A
        for(int j=0;j<n;j++){//从头遍历数组 B
            dp[j]=(A[i]==B[j]?1+dp[j+1]:0);
            max=Math.max(max,dp[j]);
        }
    }
    return max;
}

Refer to the example with a self-execution time of 35 ms

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326263289&siteId=291194637