环绕字符串中唯一的子字符串
难度:
标签:
题目描述
定义字符串 base
为一个 "abcdefghijklmnopqrstuvwxyz"
无限环绕的字符串,所以 base
看起来是这样的:
"...zabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd...."
.
给你一个字符串 s
,请你统计并返回 s
中有多少 不同非空子串 也在 base
中出现。
示例 1:
输入:s = "a" 输出:1 解释:字符串 s 的子字符串 "a" 在 base 中出现。
示例 2:
输入:s = "cac" 输出:2 解释:字符串 s 有两个子字符串 ("a", "c") 在 base 中出现。
示例 3:
输入:s = "zab" 输出:6 解释:字符串 s 有六个子字符串 ("z", "a", "b", "za", "ab", and "zab") 在 base 中出现。
提示:
1 <= s.length <= 105
- s 由小写英文字母组成
代码结果
运行时间: 62 ms, 内存: 0.0 MB
/*
* Problem statement:
* Given a string `s`, find the number of unique non-empty substrings of `s` that also appear in an infinitely repeated sequence of the English alphabet, `base = "abcdefghijklmnopqrstuvwxyz"`.
*
* Approach using Java Streams:
* 1. Use a HashSet to store unique valid substrings.
* 2. Utilize IntStream to generate start and end indices for substrings.
* 3. For each generated substring, verify its validity in the cyclic base string.
* 4. Use the helper method `isInBase` to check validity and add to set if valid.
* 5. Return the size of the set.
*/
import java.util.*;
import java.util.stream.IntStream;
public class SolutionStream {
public int findSubstringInWraproundString(String s) {
Set<String> uniqueSubstrings = new HashSet<>();
int n = s.length();
// Use IntStream to generate start and end indices
IntStream.range(0, n).forEach(i ->
IntStream.range(i + 1, n + 1).forEach(j -> {
String sub = s.substring(i, j);
if (isInBase(sub)) {
uniqueSubstrings.add(sub);
}
})
);
return uniqueSubstrings.size();
}
private boolean isInBase(String sub) {
int len = sub.length();
for (int i = 1; i < len; i++) {
if ((sub.charAt(i) - sub.charAt(i - 1) + 26) % 26 != 1) {
return false;
}
}
return true;
}
}
解释
方法:
这个题解的思路是使用一个长度为26的数组c来记录以每个字母结尾的最长连续子串的长度。遍历字符串s,如果当前字符和前一个字符的ASCII码差为1或-25(说明是相邻的字母),则继续维护当前的连续子串;否则,更新数组c中对应字母的最大长度,并重新开始一个新的连续子串。最后,从后往前遍历数组c,如果前一个字母的最长子串长度比当前字母的最长子串长度大1,则更新当前字母的最长子串长度。最终数组c中的所有元素之和即为所求的不同非空子串的数量。
时间复杂度:
O(n)
空间复杂度:
O(1)
代码细节讲解
🦆
题解中提到的数组c用来记录以每个字母结尾的最长连续子串的长度,如何处理字符的循环性,即从'z'到'a'的过渡?
▷🦆
题解中的算法在遇到当前字符和前一个字符不是相邻的情况下,为什么要更新连续子串的起始位置?这样的更新对结果的正确性有何影响?
▷🦆
在遍历数组c时,使用了从后往前的方法来更新数组元素,这种方法的目的是什么?它如何帮助我们获得正确的子串数量?
▷🦆
题解中在处理最后一个连续子串时直接更新了数组c,如果最后一个字母在前面已经有了更长的记录,这种处理方式是否会导致结果出错?
▷