一开始在想关于回文串的操作,直到我意识到这个数据范围
d[i]表示前i个字符进行操作能够得到的不同串数量.
那么转移分为两部分,一部分是当前这个位置不动,加上前i-1个位置的答案;另一个部分是将以i结尾的某个区间翻转.注意如果直接算这两个部分会有一部分是重叠的,所以进行翻转操作的区间起点不能和当前位置一样.
综上,d[i]=d[i-1]+sum-cnt[s[i]-'a']
.其中sum是之前字符的数量,cnt分别统计不同字母的数量.
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=2e5+5;
int n;
ll d[MAXN],cnt[30],sum;
char s[MAXN];
int main(){
scanf("%s",s+1);
n=strlen(s+1);
d[1]=1,sum=1,cnt[s[1]-'a']=1;
for(int i=2;i<=n;i++){
d[i]=(ll)d[i-1]+sum-cnt[s[i]-'a'];
cnt[s[i]-'a']++;
sum++;
}
printf("%lld",d[n]);
}