输入一个仅由可见字符组成的字符串 s。现在要求从中找出一个连续的最长子串,保证这个子串每一位字符都不相同。如果找到多个长度相同的子串,请输出字典序最大的。 输入 字符串 s。 输出 按要求输出的字符串 t。c++
时间: 2024-02-13 18:03:57 浏览: 64
求两个字符串的最长公共字串。
4星 · 用户满意度95%
以下是 C++ 的实现,使用了双指针和哈希表来解决问题:
```cpp
#include <iostream>
#include <unordered_map>
using namespace std;
string findLongestSubstring(string s) {
int n = s.size();
int left = 0, right = 0, maxLen = 0, start = 0;
unordered_map<char, int> lastIndex;
while (right < n) {
char c = s[right];
if (lastIndex.count(c) && lastIndex[c] >= left) {
left = lastIndex[c] + 1;
}
lastIndex[c] = right;
int len = right - left + 1;
if (len > maxLen) {
maxLen = len;
start = left;
} else if (len == maxLen && s.substr(left, len) > s.substr(start, maxLen)) {
start = left;
}
right++;
}
return s.substr(start, maxLen);
}
int main() {
string s;
cin >> s;
cout << findLongestSubstring(s) << endl;
return 0;
}
```
具体思路是:
1. 使用双指针 `left` 和 `right` 来遍历字符串,初始化为 0。
2. 使用哈希表 `lastIndex` 记录每个字符最后出现的位置。
3. 当遍历到一个字符 `c` 时,如果 `c` 的最后出现位置在 `left` 右侧,则将 `left` 更新为 `lastIndex[c] + 1`,即将左指针移到 `c` 上一次出现位置的后一位。
4. 更新 `lastIndex[c]` 的值为 `right`,即将 `c` 最后出现位置更新为当前位置。
5. 计算当前子串长度 `len = right - left + 1`,如果 `len` 大于 `maxLen`,则更新 `maxLen` 和起始位置 `start`。
6. 如果 `len` 等于 `maxLen`,则比较当前子串和当前最长子串的字典序大小,如果当前子串的字典序更大,则更新 `start`。
7. 右指针 `right` 向右移动一位,重复步骤 3 到 6,直到遍历完整个字符串。
8. 返回起始位置为 `start`,长度为 `maxLen` 的子串。
时间复杂度为 $O(n)$,空间复杂度为 $O(n)$。
阅读全文