其他分享
首页 > 其他分享> > 字符串-串的最大表示-后缀数组-1163. 按字典序排在最后的子串

字符串-串的最大表示-后缀数组-1163. 按字典序排在最后的子串

作者:互联网

2020-03-13 13:48:05

问题描述:

给你一个字符串 s,找出它的所有子串并按字典序排列,返回排在最后的那个子串。

示例 1:

输入:"abab"
输出:"bab"
解释:我们可以找出 7 个子串 ["a", "ab", "aba", "abab", "b", "ba", "bab"]。按字典序排在最后的子串是 "bab"。

示例 2:

输入:"leetcode"
输出:"tcode"

提示:

1 <= s.length <= 4 * 10^5
s 仅含有小写英文字符。

问题求解:

首先看数据规模,暴力求解是肯定不行的。时间复杂度基本在O(n) / O(nlogn)级别可以通过。

本题有个点非常重要就是最大的子串一定是其后缀,试想如果最大的子串不是后缀,那么往后追加字符必然比它本身大,矛盾。

但是仅仅观察到这一步暴力求解依然只能作出O(n ^ 2)的解,如何更进一步呢?

想到后缀自然就想到后缀数组,如果使用倍增法,可以在O(nlogn)得到解,如果使用DC3/SA-IS可以在O(n)得到解,可行。

另外,本题还可以转化为字符串的最大表示,本质上是一样的。

简单的来说,字符串的最大表示和最小表示类似,就是遇到小的直接跳过即可,采用这种算法可以在O(n)的时间复杂度得到解。

方法一:字符串的最大表示

时间复杂度:O(n)

  public String lastSubstring(String s) {
        int n = s.length();
        int i = 0; 
        int j = 1;
        int k = 0;
        while (i < n && j < n && k < n) {
            int diff = s.charAt((i + k) % n) - s.charAt((j + k) % n);
            if (diff == 0) k++;
            else {
                if (diff > 0) j = j + k + 1;
                else i = i + k + 1;
                k = 0;
                if (i == j) j++;
            }
        }
        return s.substring(Math.min(i, j), n);
    }

 

方法二:后缀数组-倍增

时间复杂度:O(nlogn)

 

标签:子串,1163,后缀,复杂度,int,bab,字符串,序排
来源: https://www.cnblogs.com/hyserendipity/p/12486086.html