传送门
题解:
双向PAM板子,同时维护最长回文前缀和最长回文后缀,和原来没什么区别,只需要注意当整个串成为一个回文串的时候需要维护一下两个指针。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
static cs int Rlen=1<<22|1;
static char buf[Rlen],*p1,*p2;
inline char get_char(){
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline char peek(){
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1;
}
template<typename T>
inline T get(){
char c;
while(!isdigit(c=gc()));T num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
inline int getint(){return get<int>();}
}
using namespace IO;
using std::cerr;
using std::cout;
cs int N=4e5+5;
int son[N][26],fa[N],len[N],dep[N],now;
char s[N<<1];
int l=N,r=N-1,llast,rlast;
ll ans;
inline void init(){fa[0]=1,len[1]=-1,now=1;}
inline void push_front(char c){
s[--l]=c;int p=llast;c-='a';
while(s[l+len[p]+1]!=s[l])p=fa[p];
if(!son[p][c]){
len[++now]=len[p]+2;
int k=fa[p];
while(s[l+len[k]+1]!=s[l])k=fa[k];
fa[now]=son[k][c],dep[now]=dep[fa[now]]+1;
son[p][c]=now;
}
llast=son[p][c];
if(len[llast]==r-l+1)rlast=llast;
ans+=dep[llast];
}
inline void push_back(char c){
s[++r]=c;int p=rlast;c-='a';
while(s[r-len[p]-1]!=s[r])p=fa[p];
if(!son[p][c]){
len[++now]=len[p]+2;
int k=fa[p];
while(s[r-len[k]-1]!=s[r])k=fa[k];
fa[now]=son[k][c],dep[now]=dep[fa[now]]+1;
son[p][c]=now;
}
rlast=son[p][c];
if(len[rlast]==r-l+1)llast=rlast;
ans+=dep[rlast];
}
int Q;
signed main(){
// freopen("pam.in","r",stdin);//freopen("pam.out","w",stdout);
init();
while(islower(peek()))push_back(gc());
Q=getint();
while(Q--)switch(getint()){
case 1:while(islower(peek()))push_back(gc());break;
case 2:while(islower(peek()))push_front(gc());break;
case 3:std::cout<<ans<<"\n";break;
}
return 0;
}