【LeetCode 每日一题】1163. 按字典序排在最后的子串

248 阅读1分钟

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^5
  • s 仅含有小写英文字符。

最小表示法

当一个字符串形成一个环的时候,要比较两个字符串是否相同就会变得很困难,因为你不知道对于第二个字符串来说,以哪个字符开始比较才会和第一个字符串相同。所以我们就会想到枚举起点比较是否相同,而这样的复杂度是O(n^2)。而最小表示法这种算法可以在O ( n ) O(n)的时间解决这个问题

  1. 初始化指针 i 为 0,j 为 1;初始化匹配长度 k 为 0
  2. 比较第 k 位的大小,根据比较结果跳转相应指针。若跳转后两个指针相同,则随意选一个加一以保证比较的两个字符串不同
  3. 重复上述过程,直到比较结束
  4. 答案为 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);
     }
 };
 ​