Leetcode 718. El subarreglo de repetición más largo (DP; ventana deslizante)

Hace buen tiempo el jueves 25 de marzo de 2021 [No lamentes el pasado, no desperdicies el presente, no temas el futuro]


1. Introducción

718. La submatriz repetida más larga
Inserte la descripción de la imagen aquí

2. Solución

2.1 Programación dinámica

Inserte la descripción de la imagen aquí

class Solution {
    
    
public:
    int findLength(vector<int>& A, vector<int>& B) {
    
    
        int m = A.size(), n = B.size();
        vector<vector<int>> dp(m+1,vector<int>(n+1));
        int res = 0;
        for(int i=0;i<m;++i){
    
    
            for(int j=0;j<n;++j){
    
    
                dp[i+1][j+1] = A[i]==B[j]?dp[i][j]+1:0;
                res = max(res,dp[i+1][j+1]);
            }
        }
        return res;
    }
};

Inserte la descripción de la imagen aquí

Versión optimizada para el espacio:

class Solution {
    
    
public:
    int findLength(vector<int>& A, vector<int>& B) {
    
    
        int m = A.size(), n = B.size();
        // 始终使数组B的长度最小
        if(m<n) return findLength(B,A);
        vector<int> dp(n+1);
        int res = 0;
        for(int i=0;i<m;++i){
    
    
            // 从后往前计算dp,避免数据被覆盖
            for(int j=n-1;j>=0;--j){
    
    
                if(A[i]==B[j]) dp[j+1] = dp[j] + 1;
                else dp[j+1] = 0;
                res = max(res,dp[j+1]);
            }
        }
        return res;
    }
};

2.2 Ventana corredera (idea ingeniosa)

Para ser honesto, lo primero que pensé para esta pregunta fue el método de la ventana deslizante. La idea sigue siendo muy simple, como se muestra en la siguiente figura (fuente: solución de ventana deslizante ), pero desafortunadamente el código no está escrito,
Inserte la descripción de la imagen aquí
si lo escribe directamente de acuerdo con el proceso anterior. El código será un poco complicado, así que consideremos cambiar nuestra forma de pensar.

Hay dos tipos de alineación de matriz: el primer tipo es A sin cambios y el primer elemento de B está alineado con un elemento en A; el segundo tipo es B sin cambios y el primer elemento de A está alineado con un elemento en B. Para cada alineación, podemos calcular las submatrices repetidas con la misma posición relativa. (En resumen: alinee el primer elemento, avance por primera vez y retroceda por segunda vez )

El método de ventana corrediza también se puede podar : si la longitud común leno menos res, se puede devolver por adelantado.

class Solution {
    
    
public:
    int findLength(vector<int>& A, vector<int>& B) {
    
    
        const int lenA = A.size(), lenB = B.size();
        int res = 0;
        // A 不变,B 的首元素与 A 中的某个元素对齐
        for(int i=0;i<lenA;++i){
    
    
            int len = min(lenB, lenA-i);
            if(len<=res) continue; // 剪枝
            int maxLen = helper(A,B,i,0,len);
            res = max(res,maxLen);
        }
        // B 不变,A 的首元素与 B 中的某个元素对齐
        for(int i=0;i<lenB;++i){
    
    
            int len = min(lenA, lenB-i);
            if(len<=res) continue; // 剪枝
            int maxLen = helper(A,B,0,i,len);
            res = max(res,maxLen);
        }
        return res;
    }

	// 给出两数组的首元素索引和重合长度,计算重合部分的最长重复子数组
    int helper(vector<int>& A, vector<int>& B, int begA, int begB, int len){
    
    
        int maxLen = 0, cnt = 0;
        for(int i=0;i<len;++i){
    
    
            if(A[begA+i]==B[begB+i]) ++cnt;
            else cnt = 0;
            maxLen = max(cnt,maxLen);
        }
        return maxLen;
    }
};

Inserte la descripción de la imagen aquí


referencias

https://leetcode-cn.com/problems/maximum-length-of-repeated-subarray/solution/zui-chang-zhong-fu-zi-shu-zu-by-leetcode-solution/

https://leetcode-cn.com/problems/maximum-length-of-repeated-subarray/solution/wu-li-jie-fa-by-stg-2/

Supongo que te gusta

Origin blog.csdn.net/m0_37433111/article/details/115208629
Recomendado
Clasificación