Last Substring in Lexicographical Order
Given a string s, return the last substring of s in lexicographical order.
Example 1:
Input: "abab"
Output: "bab"
Explanation: The substrings are ["a", "ab", "aba", "abab", "b", "ba", "bab"]. The lexicographically maximum substring is "bab".Example 2:
Input: "leetcode"
Output: "tcode"Note:
1 <= s.length <= 4 * 10^5s contains only lowercase English letters.
Explanation
Consider the following cases:
Input: zyxbzyxa
Expected output: zyxbzyxa
Input: zyxbzyxc
Expected output: zyxcWe have two index pointers, i and j. i will always be set to the index of the final substring result. j is a moving lookahead index pointer that is used to loop through and compare the character at j with the character at i.
When s[i] and s[j] are the same (the first z and the second z in the above example), we need to compare the characters next to them (the first y and the second y). Since they are the same, we need to compare the characters next to them (the first x and the second x), and so on. To achieve this, we use an offset k to compare the k character next to i and j. Note that k starts at 0, and this is essentially comparing characters s[i+k] and s[j+k].
When s[i+k] is bigger than s[j+k], we just need to let i remain as is, continue move j forward to the next character at j+k+1, and reset k back to 0.
When s[i+k] is smaller than s[j+k], this means that the substring starting at j is a better result than the substring at i. At this point, there are two situations to consider:
When
jis more thani+k: Consider an inputhhhccchhhddd, wheniis 0,jis 6, andkis 3, bothiandjare pointing toh, and you are comparing the firstcand the firstd. You would want to seti = j.When
jis less thani+k: Consider an inputnnnp, wheniis 0,jis 1, andkis 2, you are comparing the lastnandp. You would want to changeito point top, so you need to seti = i+k+1. Note that in this case, even thoughjis equal toi+1,jis not always equal toi+1(see situation 1 above), and hence you should not usei = j+k.
So with the above considerations, when s[i+k] is smaller than s[j+k], we can simply set i = Math.max(i + k + 1, j).
In the end, the result would be the substring starting at i.
class Solution {
public String lastSubstring(String str) {
int i = 0; // index of final substring.
int j = 1; // index of lookahead possible substring.
int k = 0; // moving offset to compare i & j.
while (j + k < str.length()) {
if (str.charAt(i + k) < str.charAt(j + k)) {
i = Math.max(i + k + 1, j);
j = i + 1;
k = 0;
} else if (str.charAt(i + k) > str.charAt(j + k)) {
j = j + k + 1;
k = 0;
} else {
k += 1;
}
}
return str.substring(i);
}
}Last updated