按字典序排在最后的子串
给你一个字符串 s ,找出它的所有子串并按字典序排列,返回排在最后的那个子串
1. 暴力截取比较(超时)
记录最大字符位置,暴力截取比较
class Solution {
public:
string lastSubstring(string s) {
map<char, vector<int>> m;
char mx = 'a';
for(int i=0;i<s.size();i++){
if(s[i]>mx) mx = s[i];
m[s[i]].push_back(i);
}
if(mx=='a') return s;
string res = "";
for(int i=0;i<m[mx].size();i++){
string cur = s.substr(m[mx][i]);
if(cur>res) res = cur;
}
return res;
}
};
2. 双队列逐位比较(超时)
暴力截取的优化,重复筛选当前位置,下一位置
class Solution {
public:
string lastSubstring(string s) {
int n = s.size();
map<char, queue<int>> m;
char mx = 'a';
for(int i=0;i<n;i++){
if(s[i]>mx) mx = s[i];
m[s[i]].push(i);
}
if(mx=='a') return s;
queue<int> & filter1 = m[mx];
queue<int> filter2;
int index = -1;//找最后的index
int times = 0;
while(filter1.size()!=1){
int n1 = filter1.size();
mx = 'a';
for(int i=0;i<n1;i++){//第一次筛选下一位置
int idx = filter1.front();
filter1.pop();
if(idx+1==n) continue;
if(s[idx+1]>mx) mx = s[idx+1];
filter2.push(idx+1);
}
int n2 = filter2.size();
for(int i=0;i<n2;i++){//把当前最大值的坐标还回去
int idx = filter2.front();
filter2.pop();
if(s[idx]==mx) filter1.push(idx);
}
times++;
}
return s.substr(filter1.front()-times);
}
};
3. 双指针
比较失效后,可以直接跳过比较过的位置
class Solution {
public:
string lastSubstring(string s) {
int left = 0, right = 1, n = s.size();//双指针
while (right < n) {
int step = 0;//当前比较轮次
while (right + step < n && s[left + step] == s[right + step])
step++;//相等后移比较
if (right + step < n && s[left + step] < s[right + step]) {//如果是左边的小
int t = left;
left = right;//左指针移动到右指针位置
right = max(right + 1, t + step + 1);//右指针移动到比较失效的下一位
}
else right = right + step + 1;//右指针移动到比较失效的下一位
}
return s.substr(left);
}
};