资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
对于一个字符串 ,我们定义 的分值 为 中出现的不同的字符个数。例如 "aba","abc", "aaa"。
现在给定一个字符串 (长度为 ),请你计算对于所有 的非空子串 ,的和是多少。
输入格式
输入一行包含一个由小写字母组成的字符串 。
输出格式
输出一个整数表示答案。
样例输入
ababc
Data
样例输出
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
思路:根据样式输出看出规律
- 第一个字符a他只出现了五次,我们就可以相当于用它的下标(假设下标从0开始),就可以得到(下标 + 1)x(s长度 - 下标) = 1x5 = 5,并且把a出现的位置记录下来,a的位置为1。
- 第二个字符b同理出现的次数为(下标 + 1)x(s长度 - 下标)= 2x4 = 8,并且把b的位置记录下来,b位置为2。
- 第三个字符是a,此前a的位置已经出现过了,实质第三个a出现过9次,但根据题目有用的只有6次,这里就可以用到((s长度 - 下标))x((当前位置 - 前一个位置)) = 3x2 = 6。
- 第四个同理第三个a,((s长度 - 下标))x((当前位置 - 前一个位置)) = 2x2 = 4。
- 第五个字符c还没有出现过所以直接(下标 + 1)x(s长度 - 下标) = 5x1 = 5。
从而得到ababc对应得是5,8,6,4,5加起来28。
#include<stdio.h>
#include<string.h>
int main()
{
long long i,n,sum = 0;
int a[26] = {0}; //代表每个字符的出现位置当为0的时候表示之前没有出现过
char s[100000];
scanf("%s",s);
n = strlen(s);
for(i = 0; i < n; i++)
{
if(a[s[i] - 'a'] == 0) //判断该字符是否出现过
{
sum = sum + (i + 1)*(n - i); //把单个字符的值加起来((下标 + 1)x(s长度 - 下标) )
a[s[i] - 'a'] = i + 1; //保存字符的位置
}
else
{
sum = sum + (i + 1 - a[s[i] - 'a']) * (n - i); //之前出现过的字符,现在再次出现的值((s长度 - 下标))x((当前位置 - 前一个位置))
a[s[i] - 'a'] = i + 1; //更新位置
}
}
printf("%lld",sum);
return 0;
}