2872. 子串分值和
题目链接
2872. 子串分值和
对于一个字符串 \(S\) ,我们定义 \(S\) 的分值 \(f(S)\) 为 \(S\) 中出现的不同的字符个数。
例如 \(f(" a b a ")=2, f(" a b c ")=3, f(" a a a ")=1\) 。
现在给定一个字符串 \(S[0 . . n-1]\) (长度为 \(n\) ),请你计算对于所有 \(S\) 的非空子串 \(S[i . . j](0 \leq i \leq j<n)\) , \(f(S[i . . j])\) 的和是多少。
输入格式
输入一行包含一个由小写字母组成的字符串 \(S\) 。
输出格式
输出一个整数表示答案。
数据范围
对于 \(20 \%\) 的评测用例, \(1 \leq n \leq 10\) ;
对于 \(40 \%\) 的评测用例, \(1 \leq n \leq 100\) ;
对于 \(50 \%\) 的评测用例, \(1 \leq n \leq 1000\) ;
对于 \(60 \%\) 的评测用例, \(1 \leq n \leq 10000\) ;
对于所有评测用例, \(1 \leq n \leq 100000\) 。
输入样例:
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
解题思路
思维
考虑每一个字符的贡献,先复制上一个字符的贡献,加上当前字符作为唯一出现的贡献,即与上次出现的距离,该字符上次出现前的贡献已经统计在了复制的贡献中了
- 时间复杂度:\(O(n)\)
代码
#include<bits/stdc++.h>
#define fi first
#define se second
#define help {cin.tie(NULL);cout.tie(NULL);}
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
template <typename T> bool chkMax(T &x,T y){return (x<y?x=y,1:0);}
template <typename T> bool chkMin(T &x,T y){return (x>y?x=y,1:0);}
template <typename T> inline void read(T &x)
{
int f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();
}
while(s>='0'&&s<='9'){x+=x*10+(s^48),s=getchar();
}
x*=f;
}
string s;
int p[26],cnt[26];
int main()
{
cin>>s;
int n=s.size();
s=' '+s;
LL res=0;
int lst=0;
for(int i=1;i<=n;i++)
{
int t=s[i]-'a';
lst+=i-p[t];
res+=lst;
p[t]=i;
}
cout<<res;
return 0;
}