📜  计算环绕字符串存在的字符串S 的唯一子字符串(1)

📅  最后修改于: 2023-12-03 15:12:04.634000             🧑  作者: Mango

计算环绕字符串存在的字符串S 的唯一子字符串

问题描述

给定一个被包围的字符串S,例如“abc”被“bcd”的环绕字符串包围。我们需要找出所有唯一的子字符串(不包括重复的子字符串)。

解决方案
思路
  1. 定义一个布尔型数组valids,表示当前位置是否是唯一子字符串的结尾。
  2. 定义一个HashSet,用于保存所有唯一的子字符串。
  3. 定义两个指针startend,表示唯一子字符串的起始位置和终止位置。
  4. 从左到右遍历环绕字符串S,如果当前位置是唯一子字符串的结尾,则将其保存到HashSet中,并将valids数组中相应位置标记为true
  5. 如果当前位置不是唯一子字符串的结尾,但前一个位置是,则从前一个位置开始向前遍历,直到找到一个位置使得从这个位置开始到当前位置的子字符串是唯一的。如果这个子字符串没被保存过,则将其保存到HashSet中,并将valids数组中相应位置标记为true
  6. 重复上述步骤直到遍历完整个环绕字符串S。
代码实现
public static Set<String> findUniqueSubstrings(String S) {
    Set<String> result = new HashSet<>();
    int len = S.length();
    boolean[] valids = new boolean[len];
    for (int end = 0; end < len; end++) {
        if (valids[end]) {
            result.add(S.substring(end, end + 1));
            continue;
        }
        int start = end;
        while (start > 0 && !valids[start - 1] && S.charAt(start - 1) != ((S.charAt(start) - 1) % 26 + 'a')) {
            start--;
        }
        String sub = S.substring(start, end + 1);
        if (!result.contains(sub)) {
            result.add(sub);
            valids[end] = true;
        }
    }
    return result;
}
性能分析
  • 时间复杂度:$O(n^2)$,其中n为环绕字符串S的长度。代码中有两个while循环,分别需要遍历所有能够组成唯一子字符串的区间。在最坏情况下,S为由相同字母重复若干次得到的字符串,此时时间复杂度为$O(n^2)$。
  • 空间复杂度:$O(n)$,主要是HashSet和valids数组的空间开销,都需要存储n个元素。