回文树学习
代码是模仿ctl学长的。ctlnb!!!
https://blog.csdn.net/u013368721/article/details/42100363 推荐博客
/*
user: sky48
language: c++
for dream for young
*/
#include<iostream>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define N 300005
typedef long long ll;
using namespace std;
int cnt[N],len[N],fail[N],s[N],to[N][30];
ll ans;
char ch[N];
int tot,n,L,last;
int gets()
{
int v=0; char ch;bool f=0;
while(!isdigit(ch=getchar())) if(ch=='-') f=1; v=ch-48;
while( isdigit(ch=getchar())) v=(v<<1)+(v<<3)+ch-48;
return f?-v:v;
}
void add(int c){
s[++n]=c;
int cur,tmp,now;
for(cur=last;s[n-len[cur]-1]!=s[n];cur=fail[cur]);
if(!to[cur][c]){
len[++tot]=len[cur]+2; now=tot;
for(tmp=fail[cur];s[n-len[tmp]-1]!=s[n];tmp=fail[tmp]);
fail[now]=to[tmp][c];
to[cur][c]=now;
}last=to[cur][c];
cnt[last]++;
}
int main ()
{
// freopen("tt.txt","r",stdin);
scanf("%s",ch); L=strlen(ch);
len[tot]=0, len[++tot]=-1;
fail[0]=1, fail[1]=1, s[0]=-1;
rep(i,0,L-1) add(ch[i]-'a');
for(int i=tot;i>=2;i--) cnt[fail[i]]+=cnt[i];
rep(i,2,tot) ans=max(ans,(ll)cnt[i]*len[i]);
printf("%lld\n",ans);
return 0;
}
首先,记住,to[x][c]这个是构成树,是用来统计答案的。
而fail[x]是失配以后跳的
now是树上的节点编号。