题意:定义一个字符串的价值为该字符串出现的不同字母的数量,现在给你一个字符串,求其所有回文子串的价值之和
思路:预处理一下字符串每个字母出现的位置,manacher求出以位置i为对称轴的回文串的最大半径r,枚举26个字母,二分找出每个字母第一个大于等于i的位置z,然后计算这个字母的贡献ans+=i+r-z就行了
代码:
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=3e5+9;
vector<int>vec[26];
long long ans=0;
int p[2*maxn];
void manacher(string s){
string s_new="&#";
int mx=0,pos=0,st;
for(int i=0;i<s.size();i++){
s_new+=s[i];
s_new+='#';
}
for(int i=0;i<s_new.size();i++){
if(i<mx)p[i]=min(p[2*pos-i],mx-i);
else p[i]=1;
while(i-p[i]>0&&s_new[i+p[i]]==s_new[i-p[i]])p[i]++;
if(i%2==0)st=i/2;
else st=i/2+1;
for(int j=0;j<26;j++){
int ps=lower_bound(vec[j].begin(),vec[j].end(),st)-vec[j].begin();
if(ps!=vec[j].end()-vec[j].begin()){
int r=(p[i]-1)%2==0?(p[i]-1)/2:p[i]/2;
if(vec[j][ps]<st+r){
ans+=st+r-vec[j][ps];
}
}
}
if(i+p[i]>mx){
mx=i+p[i];
pos=i;
}
}
}
int main(){
ios::sync_with_stdio();
cin.tie(0);
int i,j,k;
string s;
cin>>s;
for(i=0;i<s.size();i++){
vec[s[i]-'a'].push_back(i+1);
}
manacher(s);
cout<<ans<<endl;
}