1163. 按字典序排在最后的子串
难度:困难
时间:2023/04/24
给你一个字符串 s ,找出它的所有子串并按字典序排列,返回排在最后的那个子串。
示例 1:
输入:s = "abab"
输出:"bab"
解释:我们可以找出 7 个子串 ["a", "ab", "aba", "abab", "b", "ba", "bab"]。按字典序排在最后的子串是 "bab"。
示例 2:
输入:s = "leetcode"
输出:"tcode"
提示:
1 <= s.length <= 4 * 10^5s仅含有小写英文字符。
最小表示法
当一个字符串形成一个环的时候,要比较两个字符串是否相同就会变得很困难,因为你不知道对于第二个字符串来说,以哪个字符开始比较才会和第一个字符串相同。所以我们就会想到枚举起点比较是否相同,而这样的复杂度是O(n^2)。而最小表示法这种算法可以在O ( n ) O(n)的时间解决这个问题
- 初始化指针 i 为 0,j 为 1;初始化匹配长度 k 为 0
- 比较第 k 位的大小,根据比较结果跳转相应指针。若跳转后两个指针相同,则随意选一个加一以保证比较的两个字符串不同
- 重复上述过程,直到比较结束
- 答案为 i, j 中较小的一个
解题思路:
- i = 0,j = 1,k = 0,表示从i开始k长度和从j开始k长度的字符串相同(i,j表示当前判断的位置)
- 当str[i] == str[j]时,根据上面k的定义,需要进行k+1操作
- 当str[i] > str[j]时,i位置比j位置上字典序要大,那么不能使用j作为开头了,我们要将j向后移动,移动多少呢?因为i开头和j开头的有k个相同的字符,那么就执行 j + = k +1
- 相反str[i] < str[j]时,执行:i + = k +1
- 若滑动后i == j,统一 j + =1
class Solution {
public:
string lastSubstring(string s) {
int l = 0, r = 1, k = 0, n = s.size();
while(r + k < n){
if(s[l + k] == s[r + k]) k++;
else if(s[l] < s[r + k]){
l = r + k;
r = l + 1;
k = 0;
}
else if(s[l + k] < s[r + k]){
l = r;
r++;
k = 0;
}
else{
r++;
k = 0;
}
}
return s.substr(l);
}
};