题源ECNU2021年软工机试第二题:2021年ECNU软工考研复试机试(E组) – malic
EOJ没有开放这题,可以去leetcode测评:3. 无重复字符的最长子串 - 力扣(LeetCode)
思路:
1.采用区间滑动的思想,定义一个left和一个right,left~right之间为符合要求的子串,最长子串长度len=max(right-left+1,len)
2.下面只要处理left和right的移动使得区间内是符合要求的子串(没有重复字母):
思路如下:
(1)定义一个map<char,int> 记录每个字符出现的字符串下标例如abcd,a的下标为0,b的下标为1...,每处理完一个字符,right++区间右端点右移
(2)然后分成两种情况处理:
a)区间右端点未出现过,说明它加入区间必定会增加子串长度,修改其字符对应的map值
b)区间右端点出现过,通过map查找到它上次出现时的下标
b1)若下标k在区间内(left~right之间)说明此区间已经不符合条件,对区间左端点修改,修改的值为k+1,并将右端点字符在map中的值修改为当前右端点的下标;
b2)若下标不在区间内(left~right之间),说明不影响区间滑动,不用改变区间左端点,将右端点字符在map中的值修改为当前右端点的下标(例如pwwkep最后一个p的处理便是在这一情况中)
#include <bits/stdc++.h>
using namespace std;
int main()
{
// freopen("in.txt", "rt", stdin);
// freopen("out.txt", "wt", stdout);
string s;
cin >> s;
unordered_map<char, int> window;
int left = 0, right = 0, len = 0;
while (right < s.length())
{
// 新加入的字符没有出现在滑动窗口里面
if (window.find(s[right]) == window.end())
{
window[s[right]] = right;
}
else
{
// 新加入的字符在滑动窗口里面有
if(window[s[right]]<=right&&window[s[right]]>=left)
{
int temp = window[s[right]];
left = temp + 1;
}
window[s[right]]=right;
}
len = max(len, right - left + 1);
right++;
}
cout << len;
}