最长重复子数组

    技术2022-07-10  130

    LeetCode算法网站算法题

    https://leetcode-cn.com/problems/maximum-length-of-repeated-subarray/

    一.动态规划

    上来就瞎搞动态规划!!!

    class Solution { public: int findLength(vector<int>& A, vector<int>& B) { int a=A.size(); int b=B.size(); vector<vector<int>>dp(a+1,vector<int>(b+1,0)); for(int i=1;i<=a;i++) { for(int j=1;j<=b;j++) { if(A[i-1]==B[j-1]) dp[i][j]=dp[i-1][j-1]+1; else dp[i][j]=max(dp[i-1][j],dp[i][j-1]); } } return dp[a][b]; } };

    后来在这个测试用例垮掉了!!

    想了一下,可能我把dp[i][j]理解为A组中前i个数据与B组中前j个数据的最长公共子串的长度有失偏颇,正确应当是以A组中第i个数据和B组中第j个数据为最长公共子串的最后一个公共数据的最长公共子串的长度,所以当A[i]与B[j]不相等的时候dp[i][j]应该被赋值为0,否则像我第一次写的代码那样可能计算出来的就是两个数组的最长公共子序列了!!

    更正DP

    class Solution { public: int findLength(vector<int>& A, vector<int>& B) { int a=A.size(); int b=B.size(); int ans=0; vector<vector<int>>dp(a+1,vector<int>(b+1,0)); for(int i=1;i<=a;i++) { for(int j=1;j<=b;j++) { if(A[i-1]==B[j-1]) dp[i][j]=dp[i-1][j-1]+1; else dp[i][j]=0; ans=max(ans,dp[i][j]); } } return ans; } };

    二.滑动窗口

    思路就是,先把A数组相对于B数组向前滑动,findMax函数就是查找此时A,B数组相交的两部分的最长公共子串,但是仅这样滑动一次,每次都是包含B数组的前边一部分,所以这样会与正确答案有差异,因此需要再次把B数组相对A数组向前滑动,这样就可以每次计算都包含B数组的后面那部分了!!!!所以两次滑动并同时更新就可以获得正确答案!!

    class Solution { private: int findMax(vector<int>&A,vector<int>&B,int sa,int sb,int&len) { int i; int k=0; int res=INT_MIN; for(i=0;i<len;i++) { if(A[sa+i]==B[sb+i]) k++; else k=0; res=max(res,k); } return res; } public: int findLength(vector<int>& A, vector<int>& B) { int a=A.size(); int b=B.size(); int ans=INT_MIN; for(int i=0;i<a;i++) { int len=min(a-i,b); int maxlen=findMax(A,B,i,0,len); ans=max(ans,maxlen); } for(int i=0;i<b;i++) { int len=min(b-i,a); int maxlen=findMax(A,B,0,i,len); ans=max(ans,maxlen); } return ans; } };

    三.二分查找+哈希——无情的复制粘贴,我一看这么长,不如前面两个好想也不好操作就没怎么看,以后有时间了可以看看拓展一下思路!!

    class Solution { public: const int mod = 1000000009; const int base = 113; // 使用快速幂计算 x^n % mod 的值 long long qPow(long long x, long long n) { long long ret = 1; while (n) { if (n & 1) { ret = ret * x % mod; } x = x * x % mod; n >>= 1; } return ret; } bool check(vector<int>& A, vector<int>& B, int len) { long long hashA = 0; for (int i = 0; i < len; i++) { hashA = (hashA * base + A[i]) % mod; } unordered_set<long long> bucketA; bucketA.insert(hashA); long long mult = qPow(base, len - 1); for (int i = len; i < A.size(); i++) { hashA = ((hashA - A[i - len] * mult % mod + mod) % mod * base + A[i]) % mod; bucketA.insert(hashA); } long long hashB = 0; for (int i = 0; i < len; i++) { hashB = (hashB * base + B[i]) % mod; } if (bucketA.count(hashB)) { return true; } for (int i = len; i < B.size(); i++) { hashB = ((hashB - B[i - len] * mult % mod + mod) % mod * base + B[i]) % mod; if (bucketA.count(hashB)) { return true; } } return false; } int findLength(vector<int>& A, vector<int>& B) { int left = 1, right = min(A.size(), B.size()) + 1; while (left < right) { int mid = (left + right) >> 1; if (check(A, B, mid)) { left = mid + 1; } else { right = mid; } } return left - 1; } };

     

    Processed: 0.017, SQL: 9