时间限制: 1s 内存限制: 128MB 提交: 1387 解决: 396
题目描述
对于一个字符串S,我们定义S 的分值 f(S) 为S中恰好出现一次的字符个数。例如f (”aba”) = 1,f (”abc”) = 3, f (”aaa”) = 0。
现在给定一个字符串S[0…n-1](长度为n),请你计算对于所有S的非空子串S[i…j](0 ≤ i ≤ j < n), f (S[i… j]) 的和是多少。
输入格式
输入一行包含一个由小写字母组成的字符串S。
输出格式
输出一个整数表示答案。
样例输入
复制
ababc
样例输出
复制
21
提示
样例说明:
子串f值:
a 1
ab 2
aba 1
abab 0
ababc 1
b 1
ba 2
bab 1
babc 2
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。
从C语言网学来的方法,思路十分巧妙。
#include <bits/stdc++.h> using namespace std; int m[27][3];//存值,0,1,2三个下标分别代表现在所处位置和前两个所处位置 string s; int main() { cin>>s; int i; long long sum=0; long long qian=0; for(i=0;i<s.length();i++) { int x=s[i]-'a'; m[x][0]=i+1;//存位置 qian=qian+(m[x][0]-m[x][1])-(m[x][1]-m[x][2]);//可能出现在的字串数 sum=sum+qian; m[x][2]=m[x][1];//更新状态 m[x][1]=m[x][0];//更新状态 } printf("%d\n",sum); return 0; }
还有一种是我自己写的,但会超时,思路也比较简单,使用set直接遍历,可以快速拿分。
#include <iostream> #include <set> #include <vector> using namespace std; int main() { string s; set<char> s1; int cnt = 0; int t = 0; cin >> s; int size = s.size(); for (int i = 0; i < size; i++) { s1 = {}; for (int j = i; j < size; j++) { s1.insert(s[j]); cnt += s1.size(); t++; } } cout << cnt; return 0; }