我的想法是以F[i]表示以第i位字母结尾的字串总价值,当前的价值 = 上一位的价值 + str[i]产生新字母的字串的价值 - str[i]产生重复字母的价值,那么转移方程分为:
1. str[i]第一次出现, f[i] = f[i - 1] + i。
2. str[i]第二次出现,f[i] = f[i - 1] + (i - pos[c][1]) - (pos[c][1] - 0)
3. str[i]已多次出现,f[i] = f[i - 1] + (i - pos[c][cnt[c] - 1]) - (pos[c][cnt[c] - 1] - pos[c][cnt[c] - 2])
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
int n;
int f[N];
char str[N];
unordered_map<char, int> cnt, pos[N];
int main()
{
cin >> str + 1;
n = strlen(str + 1);
LL res = 0;
for (int i = 1; i <= n; ++ i)
{
char c = str[i];
pos[c][++ cnt[c]] = i;
switch (cnt[c])
{
case 1 :
f[i] = f[i - 1] + i;
break;
case 2 :
f[i] = f[i - 1] + (i - pos[c][1]) - (pos[c][1] - 0);
break;
default :
f[i] = f[i - 1] + (i - pos[c][cnt[c] - 1]) - (pos[c][cnt[c] - 1] - pos[c][cnt[c] - 2]);
}
res = res + (LL)f[i];
}
cout << res << endl;
return 0;
}