题意
定义一个字符串的值为字符串中不同字符的种数,求一个字符串的所有回文子串的值的和。
题解
算是回文自动机的板子题,可惜之前做的时候没学,直接构建回文树,dfs统计就行了。
写这个还是为了完善一下回文自动机的模板,之前写的那个模板不好用。
代码
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
using namespace std;
typedef long long LL;
const int N=3e5+10;
char s[N];
int n;
LL ans;
struct PAM{
int tr[N][26],fail[N],len[N],cnt[N],tot,last,n;
int getfail(int x){
while(s[n]!=s[n-len[x]-1]) x=fail[x];
return x;
}
void init(char *s){
n=tot=last=0;
cnt[0]=len[0]=cnt[1]=0;
memset(tr[0],0,sizeof(tr[0]));
memset(tr[1],0,sizeof(tr[1]));
fail[0]=1;
len[++tot]=-1;
for(n=1;s[n]!=' ';n++){
int c=s[n]-'a',cur=getfail(last);
if(!tr[cur][c]){
len[++tot]=len[cur]+2;cnt[tot]=0;
memset(tr[tot],0,sizeof(tr[tot]));
fail[tot]=tr[getfail(fail[cur])][c];
tr[cur][c]=tot;
}
last=tr[cur][c];
cnt[last]++;
}
for(int i=tot;i>=0;i--) cnt[fail[i]]+=cnt[i];
}
int count,vis[26];
void dfs(int u){
ans+=count*cnt[u];
for(int i=0;i<26;i++){
if(!tr[u][i]) continue;
vis[i]++;if(vis[i]==1) count++;
dfs(tr[u][i]);
vis[i]--;if(!vis[i]) count--;
}
}
}pam;
int main(){
scanf("%s",s+1);
pam.init(s);
pam.dfs(0);
pam.dfs(1);
cout<<ans<<endl;
return 0;
}