每个字母只有在第一次出现时才有贡献度,因此可以统计每个字母在第一次出现的情况下,能被多少子串所包含
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
#define int long long
int id[30];//上一次出现的下标
string s;
signed main()
{
cin >> s;
int n = s.size();
s = " "+ s;
ll ans = 0;
for (int i = 1; i <= n; i ++)
{ //此时下标自己,必包含自己的子串右边*左边不包含自己的
ans +=(i - id[s[i]-'a']) * (n - i + 1);
id[s[i]-'a'] = i;
}
cout << ans << endl;
return 0;
}
耐摔指数DP
#pragma GCC optimize(3,"Ofast","inline")
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
#define int long long
#define ld long double
int n,dp[4][10010];
void solve()
{
cin>>n;
for(int i=1;i<=3;i++)
for(int j=1;j<=n;j++)
dp[i][j]=j;//初始化最大值
for(int i=2;i<=3;i++)
for(int j=1;j<=n;j++){//还有j层测试时
for(int k=1;k<=j;k++) {//枚举k层,在第k层时候摔下当前手机手机
//如果手机坏了,dp[i-1][k-1]
//没坏,那么还剩下j-k层没有检测
int ti=max(dp[i-1][k-1],dp[i][j-k])+1;//最坏情况
dp[i][j]=min(dp[i][j],ti);
}
}
cout<<dp[3][n];
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
solve();
return 0;
}