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;
}