试题 H: 子串分值和
时间限制: 1.0s 内存限制: 256.0MB 本题总分:20 分
【问题描述】
对于一个字符串 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。
【输出格式】
输出一个整数表示答案。
【样例输入】
ababc
【样例输出】
28
【样例说明】
子串 f值 a 1
ab 2
aba 2
abab 2
ababc 3
b 1
ba 2
bab 2
babc 3
a 1
ab 2
abc 3
b 1
bc 2
c 1
【评测用例规模与约定】
对于 20% 的评测用例,1 ≤ n ≤ 10;
对于 40% 的评测用例,1 ≤ n ≤ 100;
对于 50% 的评测用例,1 ≤ n ≤ 1000;
对于 60% 的评测用例,1 ≤ n ≤ 10000;
对于所有评测用例,1 ≤ n ≤ 100000。
思路:
以ababc为例
定义一个数组存放每个字母出现的次数,len表示不是0的字母的个数
第一次for循环从左往右
那么每访问一个字符,次数++
当前串 | 状态 |
---|---|
a | len = 1 ,a = 1 |
ab | len = 2 ,a = 1, b = 1 |
aba | len = 2 , a = 2, b = 1 |
abab | len = 2 ,a = 2, b = 2 |
ababc | len = 3 , a = 2, b = 2, c = 1 |
接下来,for循环从左到右,但是删除字符串最左边的值
当前串 | 状态 |
---|---|
babc | a-- , len = 3 a = 1, b = 2, c = 1 |
abc | b-- , len = 3 a = 1, b = 1, c = 1 |
bc | a-- , len = 2 a = 0, b = 1, c = 1 |
c | b-- ,len = 1 a = 0, b = 0, c = 1 |
由此可见,两次循环下去只用O(2N)的时间求出来大量的需要累加的字符串
但是ababc中间的子串bab以及以此为基础的字串都没有被考虑到,所以此时,只需要在外层新加一层循环,l=0,r = str.length() ,只要l<r,就循环,然后l++,r- -,最后就能考虑到所有的情况
代码:
由于今天刚考完担心被查重系统误判,故放下图片,不放源码,同理,不保证代码正确: