718[Medium]:Maximum Length of Repeated Subarray

Part1:問題描述

Given two integer arrays A and B, return the maximum length of an subarray that appears in both arrays.

Example 1:

Input:
A: [1,2,3,2,1]
B: [3,2,1,4,7]
Output: 3
Explanation: 
The repeated subarray with maximum length is [3, 2, 1].

Note:

  1. 1 <= len(A), len(B) <= 1000
  2. 0 <= A[i], B[i] < 100

Part2:解題思路

1.公共子序列和公共子串

公共子序列:在母串中都出現過且出現順序與母串保持一致的字符組成的序列,不要求連續

公共子串:更嚴格的公共子序列,公共子串是在母串中連續的公共子序列。

例如:

字符串A:introduce

字符串B:tradition

公共子序列:ito,tro等

公共子串:i,tr等

2.動態規劃和分治

分治:每一步都會以一個特定的比例縮減問題的規模,比如第一步將問題A分成A/2,A/2,第二部將每個A/2分爲A/4,A/4以此類推。

動態規劃:也是將大問題劃分爲小問題,但是縮減的規模不用以一個特定的倍數,每次只需要是原來的問題變小一點就可以。通常可以先寫出動態規劃的狀態方程,按照方程寫代碼不要太簡單。

3.最長公共子序列和最長公共子串的動態規劃的狀態方程及解釋

(1)求字符串A,B的最長公共子序列(字符串下標從0開始):

dp[i][j]:表示字符串A的前i位字符串和B的前j位字符串中最長公共子序列的長度


(2)求字符串A,B的最長公共子串(字符串下標從0開始):

dp[i][j]:表示字符串A的前i位字符串和B的前j位字符串中最長公共後綴的長度。因爲是後綴,所以必然是連續子串且至少最後一個字符要相等

因爲這裏字符串的下標從0開始,所以需要對0進行處理,如果從1開始的話,就可以直接去掉對0的判斷且是直接比較A[i]和B[j],會簡單一些。


leetcode的這道題是用的整數數組,原理是一樣的,並且下標也是從0開始的。根據自己掛了幾次發現這個題其實是想求最長公共子串。下面的代碼在leetcode上已測試通過。

遇到的問題:

(1)要考慮清楚i,j與你要拿來判斷的某個字符下標的關係

(2)循環的範圍

Part3:代碼

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
/*
// 求最長公共子序列 
int findLength(vector<int>& A, vector<int>& B) {
	int a = A.size();
	int b = B.size(); 
	int result = 0;
	int** dp = new int*[a + 1];
	for (int i = 0; i < a+1; i++) {
		dp[i] = new int[b + 1];
	}
	for (int i = 0; i < a+1; i++) {
		for (int j = 0; j < b+1; j++) {
			dp[i][j] = 0;
		}
	}
	// i表示A的前i位子串
	// j表示B的前j位子串 
	// 由於字符串從0開始i,j不是我們要比較的那個字符的下標,要考慮清楚ij與我們要用的下標的關係和循環的範圍 
	for (int i = 0; i <= a; i++) {
		for (int j = 0; j <= b; j++) {
			if (i == 0 || j == 0) {
				dp[i][j] = 0;
			} else if (A[i- 1] == B[j - 1]) {
				dp[i][j] = 1 + dp[i - 1][j - 1];
			} else {
				dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
			}
			if (dp[i][j] > result) {
				result = dp[i][j];
			} 
		}
	}
	return result;
}
*/

// 求最長公共子串 
int findLength(vector<int>& A, vector<int>& B) {
	int a = A.size();
	int b = B.size(); 
	int result = 0;
	int** dp = new int*[a + 1];
	for (int i = 0; i < a+1; i++) {
		dp[i] = new int[b + 1];
	}
	for (int i = 0; i < a+1; i++) {
		for (int j = 0; j < b+1; j++) {
			dp[i][j] = 0;
		}
	}
	// i表示A的前i位子串
	// j表示B的前j位子串 
	// 由於字符串從0開始i,j不是我們要比較的那個字符的下標,要考慮清楚ij與我們要用的下標的關係和循環的範圍 
	for (int i = 0; i <= a; i++) {
		for (int j = 0; j <= b; j++) {
			if (i == 0 || j == 0) {
				dp[i][j] = 0;
			} else if (A[i - 1] == B[j - 1]) {
				dp[i][j] = 1 + dp[i - 1][j - 1];
			} else {
				dp[i][j] = 0;
			}
			if (dp[i][j] > result) {
				result = dp[i][j];
			} 
		}
	}
	return result;
}

int main() {
	vector<int>A;
	vector<int>B;
	int numA, numB, temp;
	cin >> numA;
	cin >> numB;
	for (int i = 0; i < numA; i++) {
		cin >> temp;
		A.push_back(temp);
	}
	for (int i = 0; i < numB; i++) {
		cin >> temp;
		B.push_back(temp);
	}
	cout << findLength(A, B) << endl;
	return 0;
}



發佈了29 篇原創文章 · 獲贊 0 · 訪問量 2320
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章