查找包含两个唯一字符的所有子字符串的数量。
编辑:我误读了这个问题。此解决方案找到具有至少2 个唯一字符的唯一子字符串
给定单词的子字符串数,其长度len
由下式给出len * (len + 1) / 2
总和 =len * (len + 1) / 2
- 我们正在寻找长度大于 1 的子字符串。上面的公式包括长度为 1 的子字符串。我们需要减去这些子字符串。
所以现在 2 个字母子串的总数是len * (len + 1) / 2 - l
.
sum = `len * (len + 1) / 2 - l`
- 找到最长的连续字符,它们是相似的。应用步骤
1
和2
。sum
从步骤 2 中获得的减去这个当前总和。
示例实现如下。
public static int allUniq2Substrings(char s[]) {
int sum = s.length * (s.length + 1) / 2 - s.length;
int sameRun = 0;
for (int i = 0, prev = -1; i < s.length; prev = s[i++]) {
if (s[i] != prev) {
sum -= sameRun * (sameRun + 1) / 2 - sameRun;
sameRun = 1;
} else {
sameRun++;
}
}
return sum - (sameRun * (sameRun + 1) / 2 - sameRun);
}
allUniq2Substrings("aaac".toCharArray());
3
allUniq2Substrings("aabc".toCharArray());
5
allUniq2Substrings("aaa".toCharArray());
0
allUniq2Substrings("abcd".toCharArray());
6
编辑
让我再试一次。我使用上述3 个不变量。这是查找包含至少 2 个唯一字符的所有子字符串的子问题。我在上面发布了一个方法,它为我提供了任何长度的唯一子字符串。我将使用它从包含 2 个唯一字符的集合中生成子字符串。
我们只需要跟踪设置长度为 2 的最长后续字符运行。即 2 个唯一字符的任何排列。这些运行的总和为我们提供了所需子字符串的总数。
public static int allUniq2Substrings(char s[]) {
int sum = s.length * (s.length + 1) / 2 - s.length;
int sameRun = 0;
for (int i = 0, prev = -1; i < s.length; prev = s[i++]) {
if (s[i] != prev) {
sum -= sameRun * (sameRun + 1) / 2 - sameRun;
sameRun = 1;
} else {
sameRun++;
}
}
return sum - (sameRun * (sameRun + 1) / 2 - sameRun);
}
public static int uniq2substring(char s[]) {
int last = 0, secondLast = 0;
int sum = 0;
for (int i = 1; i < s.length; i++) {
if (s[i] != s[i - 1]) {
last = i;
break;
}
}
boolean OneTwo = false;
int oneTwoIdx = -1; //alternating pattern
for (int i = last + 1; i < s.length; ++i) {
if (s[secondLast] != s[i] && s[last] != s[i]) { //detected more than 2 uniq chars
sum += allUniq2Substrings(Arrays.copyOfRange(s, secondLast, i));
secondLast = last;
last = i;
if (OneTwo) {
secondLast = oneTwoIdx;
}
OneTwo = false;
} else if (s[i] != last) { //alternating pattern detected a*b*a
OneTwo = true;
oneTwoIdx = i;
}
}
return sum + allUniq2Substrings(Arrays.copyOfRange(s, secondLast, s.length));
}
uniq2substring("abaac".toCharArray())
6
uniq2substring("aab".toCharArray())
2
uniq2substring("aabb".toCharArray())
4
uniq2substring("ab".toCharArray())
1