题目描述
对于一个字符串 S,我们定义 S 的分值 f(S) 为 S 中出现的不同的字符个数。例如 f(“aba”) = 2,f(“abc”) = 3, f(“aaa”) = 1。
现在给定一个字符串 S [0...n − 1](长度为 n),请你计算对于所有 S 的非空子串 S [i...j](0 ≤ i ≤ j < n),f(S [i...j]) 的和是多少。
输入描述
输入一行包含一个由小写字母组成的字符串 S。
其中,1 ≤ n ≤ 10^5。
输出描述
输出一个整数表示答案。
输入输出样例
示例 1
输入
ababc
输出
28
运行限制
- 最大运行时间:1s
- 最大运行内存: 128M
常规思路
枚举每一种子串判断,该种方法的时间复杂度为O(n^2),会超时。在这里也给出该代码示例:
#include <bits/stdc++.h>
using namespace std;
long long ans = 0;
int main() {
string s;
cin >> s;
for (int i = 0; i < s.size(); i++) {
for (int j = 1; j <= s.size() - i; j++) {
string nowstring = s.substr(i, j);
int a[26] = {0};
for (int k = 0; k < nowstring.size(); k++) {
if (a[nowstring[k] - 'a'] == 0)
ans++;
a[nowstring[k] - 'a']++;
}
}
}
cout << ans;
return 0;
}
求字符贡献方法(复杂度O(n))
例如对于字符串ababc来说:
第一个字符:a,做出贡献的字符串:
a ab aba abab ababc(从第一个字符开始)
第二个字符:b,做出贡献的字符串:
b ba bab babc(从第二个字符开始)
ab aba abab ababc(从第一个字符开始)
第三个字符:a,做出贡献的字符串:
a ab abc(从第三个字符开始)
ba bab babc(从第二个字符开始)
第一个字符是a,第三个字符:a无法做出贡献
第四个字符:b,做出贡献的字符串:
b bc(从第四个字符开始)
ab abc(从第三字符开始)
第二个字符是b,第四个字符:b无法做出贡献
第五个字符:c,做出贡献的字符串:
c (从第五个字符开始)
bc (从第四个字符开始)
abc (从第三个字符开始)
babc (从第二个字符开始)
ababc(从第一个字符开始)
所以总计贡献就等于每个字符的贡献和:5*1 + 4*2 + 3*2 + 2*2 + 1*5
这里已经可以看出规律来了,规律在下述代码中也很容易理解
代码示例
#include <bits/stdc++.h>
using namespace std;
int last[30];
long long ans = 0;
int main() {
string s;
cin >> s;
int len = s.length();
s = '0' + s; //下标从1开始
for (int i = 1; i <= len; i++) {
ans += (long long)(len - i + 1) * (i - last[s[i]-'a']);
last[s[i]-'a'] = i;
}
cout << ans;
return 0;
}