https://nanti.jisuanke.com/t/41389
The value of a string s is equal to the number of different letters which appear in this string.
Your task is to calculate the total value of all the palindrome substring.
Input
The input consists of a single string ∣s∣(1≤∣s∣≤3×105).
The string s only contains lowercase letters.
Output
Output an integer that denotes the answer.
样例输入
abac
样例输出
6
样例解释
abac has palindrome substrings a,b,a,c,aba,ans the total value is equal to 1+1+1+1+2=6。
关于回文串首先就想到了马拉车和回文树,但是回文树并不会改(卑微)所以就考虑马拉车
我们可以用马拉车把以该点为回文中心的回文串找出来,那么这个回文子串的值是多少呢,肯定不能暴力找,否则一个全a串就给卡掉了。
虽然串可能很长,但是每个回文串的值最大26,我们可以考虑每个字符对以该点为回文中心的回文串的贡献
序列自动机预处理出该位置后每个字符第一次出现的位置,从该位置到最大回文半径都有贡献(说的不太准确,看代码应该能懂)然后暴力算一算贡献就可以了,时间复杂度应该在1e7左右
(被签到题卡成傻逼,心态崩了,编译器也崩了,真是人机合一了,呵呵)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int N=310005;
char s[N];
char a[N*2];
int p[N*2];
int pos[N][27];
int manacher(char s[],int len){
int l=0;
a[l++]='$';
a[l++]='#';
for(int i=0;i<len;i++){
a[l++]=s[i];
a[l++]='#';
}
a[l]=0;
int mx=0,id=0;
for(int i=0;i<l;i++){
p[i]=mx>i?min(p[2*id-i],mx-i):1;
while(a[i+p[i]]==a[i-p[i]]) p[i]++;
if(i+p[i]>mx){
mx=i+p[i];
id=i;
}
}
return l;
}
int main(){
while(~scanf("%s",s)){
int len=strlen(s);
int Len=manacher(s,len);
for(int i=0;i<26;i++) pos[len][i]=-1;
for(int i=len-1;i>=0;i--){
int c=s[i]-'a';
pos[i][c]=i;
for(int j=0;j<26;j++){
if(j==c) continue;
pos[i][j]=pos[i+1][j];
}
}
ll ans=0;
for(int i=1;i<Len;i++){
if(i&1){
int cnt=(p[i]-1)>>1;
int now=i>>1;
for(int j=0;j<26;j++){
if(pos[now][j]!=-1&&pos[now][j]-now<cnt) ans+=cnt-(pos[now][j]-now);
}
}
else{
int cnt=p[i]>>1;
int now=(i>>1)-1;
for(int j=0;j<26;j++){
if(pos[now][j]!=-1&&pos[now][j]-now<cnt) ans+=cnt-(pos[now][j]-now);
}
}
}
printf("%lld\n",ans);
}
return 0;
}