双指针:
从数组的第一个元素开始向后遍历的。两个指针`start`和`end`都是从数组的开始处出发。`end`指针会逐个遍历整个数组,而`start`指针只会在需要跳过重复元素时移动。
例如,对于数组 `[1,2,3,4,1,5,6,7,8,1]`,开始时`start=0`,`end=0`。当`end`遍历到第二个`1`时(即`arr[4]`),`start`指针会跳过第一个`1`,移动到`arr[1]`(即元素`2`)处。
这样,`[start, end]`区间内的子数组就没有重复元素,我们只需要记录这个区间的长度,并与目前找到的最大长度比较即可。
`lastPos`这个`unordered_map`是用来快速查找一个元素最后出现的位置,以便我们能够迅速更新`start`指针。
int maxLength(vector<int>& arr) {
if (arr.empty()) return 0;
int maxLen = 0;
unordered_map<int, int> lastPos;
int start = 0;
for (int end = 0; end < arr.size(); ++end) {
// 更新start指针位置
if (lastPos.find(arr[end]) != lastPos.end() && lastPos[arr[end]] >= start) {
start = lastPos[arr[end]] + 1;
}
// 更新元素最后出现的位置
lastPos[arr[end]] = end;
// 更新最大长度
maxLen = max(maxLen, end - start + 1);
}
return maxLen;
}
记录下标就好,然后用substr函数,str1.substr(maxIndex - maxLen, maxLen);
`substr` 是一个常用于C++ `std::string` 类中的成员函数,用于从一个字符串中提取一个子串。这个函数有两个参数:
1. `pos`(起始位置):从哪个位置开始提取子串。位置从 0 开始计数。
2. `len`(长度):要提取的子串的长度。
string LCS(string str1, string str2) {
// write code here
int maxLen = 0;
int maxIndex;
vector<vector<int>> dp(str1.size() + 1, vector<int> (str2.size() + 1, 0));
for (int i = 1; i <= str1.size(); i++) {
for (int j = 1; j <= str2.size(); j++) {
if (str1[i-1] == str2[j-1]) {
dp[i][j] = dp[i-1][j-1] + 1;
}
if (maxLen < dp[i][j]) {
maxIndex = i;
maxLen = dp[i][j];
}
}
}
string res = str1.substr(maxIndex - maxLen, maxLen);
return res;
}
注意和 最长回文子序列 不一样,类似于求 回文子串总数,用bool类型的dp,记得在当dp[i][j]=true时更新maxLen=max(maxLen, j - i +1),此外i从size()-1开始,j 从 i 开始。
int getLongestPalindrome(string A) {
// write code here
vector<vector<bool>> dp(A.size(), vector<bool>(A.size(), false));
int maxLen = 1;
for (int i = A.size() - 1; i >= 0; i--) {
for (int j = i; j < A.size(); j++) {
if (A[i] == A[j]) {
if ((j - i) <= 1) {
dp[i][j] = true;
} else if (dp[i + 1][j - 1] == true) {
if (A[i] == A[j]) {
dp[i][j] = true;
}
}
if (dp[i][j]) maxLen = max(maxLen, j - i + 1);
}
}
}
return maxLen;
}