• LeetCode 1163. 按字典序排在最后的子串


    1163. 按字典序排在最后的子串

     

    【最小表示法】

    最小表示法用在从一个循环字符串(或者不循环)的字符串中找到最小(大)的子串。

    例如:从abaabczbzd这个串中找到zd这个最大字典序子串或者zdabaabczb这样一个子串,暴力法就是从每个位置切割字符串,但是这样需要保存n*n个字符串再排序,必然MLE

    因此最小表示法的精髓在于,每次都比较两个错开的子串,如果[i + k] == [j + k] (i != j),说明这两个字符串一直都是相同的,但是我们让其错开了,所以长的那个是大的,也就是aaa,aaaa这种情况。如果k达到一个值的时候[i + k] > [j + k],则以j开头的永远不可能比以i开头的大了,也就是aab, aaa这种情况

    同时以j + k开头的比必然有以i + k开头的比他大,所以这时候j直接从j + k + 1开始继续去和i 开头的去比较。当[i + k] < [j + k]时同理。

    所以(最大表示法)算法流程为:

    1.初始化 i = 0, j = 1, k = 0;

    2.比较[i + k] 与 [j + k] 如果相等继续比较;

    3.若[i + k] > [j + k] , 则 j = j + k + 1, 否则 i = i + k + 1;

    4.若第3步执行后i == j, 令任意一个++;

    5.取min(i, j)。

    举几个🌰:

    1.abab

    (1) i = 0, j = 1, k = 0时:s[i + k] = s[0 + 0] = a, s[j + k] = s[1 + 0] = b, a < b, 故i = i + k + 1 = 1. 但是此时i==j,故将++i = 2

    (2) i = 2, j = 1, k = 0: s[i + k] = s[2 + 0] = a, s[j + k] = s[1 + 0] = b, a < b, 故i = i + k + 1 = 3

    (3) i = 3, j = 1, k = 0: s[i + k] = s[3 + 0] = b, s[j + k] = s[1 + 0] = b, a == b, 故k++

    (4) i = 3, j = 1, k = 1: i + k = 3 + 1 = 4, 跳出循环

    (5) 最终取min(i, j) = min(3, 1) = 1,所以最终答案为"bab"

    2.aaab

    (1) i = 0, j = 1, k = 0时:s[i + k] = s[0 + 0] = a, s[j + k] = s[1 + 0] = a, a == a, 故k++

    (2) i = 0, j = 1, k = 1时:s[i + k] = s[0 + 1] = a, s[j + k] = s[1 + 1] = a, a == a, 故k++

    (1) i = 0, j = 1, k = 2时:s[i + k] = s[0 + 2] = a, s[j + k] = s[1 + 2] = b, a < b, 故i = i + k + 1 = 0 + 2 + 1 = 3

    (2) i = 3, j = 1, k = 0: s[i + k] = s[3 + 0] = b, s[j + k] = s[1 + 0] = a, b > a, 故j = j + k + 1 = 1 + 0 + 1 = 2

    (3) i = 3, j = 2, k = 0: s[i + k] = s[3 + 0] = b, s[j + k] = s[2 + 0] = a, b > a, 故j = j + k + 1 = 2 + 0 + 1 = 3, 但是此时i == j,将其中一个++

    (4) i = 4, j = 3, k = 0: i 超范围了,跳出循环

    (5) 最终取min(i, j) = min(4, 3) = 3,所以最终答案为"b"

    1. class Solution {
    2. public String lastSubstring(String s) {
    3. int n = s.length();
    4. if (n == 1) return s;
    5. int i = 0, j = 1, ans = 0;
    6. while (i < n && j < n) {
    7. int k = 0;
    8. while (i + k < n && j + k < n && s.charAt(i + k) == s.charAt(j + k)) k++;
    9. if (i + k == n || j + k == n) break;
    10. if (s.charAt(i + k) > s.charAt(j + k)) {
    11. j = j + k + 1;
    12. } else {
    13. i = i + k + 1;
    14. }
    15. if (i == j) j++;
    16. }
    17. ans = Math.min(i, j);
    18. return s.substring(ans);
    19. }
    20. }
    1. class Solution {
    2. public:
    3. // 最小表示法 5:00
    4. string lastSubstring(string s) {
    5. int i = 0, j = 1, k = 0;
    6. int n = s.size();
    7. while (i < n && j < n) {
    8. k = 0;
    9. while (i + k < n && j + k < n && s[i + k] == s[j + k]) k++;
    10. if (i + k == n || j + k == n) break;
    11. if (s[i + k] > s[j + k]) {
    12. j = j + k + 1;
    13. } else {
    14. i = i + k + 1;
    15. }
    16. if (i == j) i++;
    17. cout<
    18. }
    19. cout<min(i, j)<
    20. return s.substr(min(i, j));
    21. }
    22. };

     

     

  • 相关阅读:
    第六章:Property-based Testing and Test Oracles
    苍穹外卖技术栈
    JavaScipt基础(持续更新一)
    二维码智慧门牌管理系统:确保数据准确,强制校验GPS信号强度
    SpringBoot自动配置原理解析 | 京东物流技术团队
    Stable Diffusion - 配置 WebUI 升级至 v1.6.0 版本与 VirtualENV 环境配置
    Docker进阶知识(深入浅出理解Docker)
    设计模式学习(三):工厂模式
    计算机毕业设计Java高校勤工助学管理系统(源码+系统+mysql数据库+lw文档)
    在spring中使用RequestBodyAdvice 和 ResponseBodyAdvice增强器
  • 原文地址:https://blog.csdn.net/Sasakihaise_/article/details/126186104