BZOJ传送门
洛谷传送门
解析:
PAM裸题,当然SAM也可以做。
先建立出PAM,同时每次更新last节点的cnt,然后再在fail树上一路向上跳同时上传cnt就行了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
typedef struct PAM_node *point;
struct PAM_node{
int len,cnt;
point fa,son[26];
};
cs int N=300005;
struct PAM{
PAM_node nd[N];
point last,now;
int n;char s[N];
PAM(){
s[0]='#';
nd[0].fa=nd+1;
nd[1].fa=nd;
nd[0].len=0;
nd[1].len=-1;
last=nd;now=nd+1;
}
inline void push_back(char c){
c-='a';s[++n]=c;
while(s[n-1-last->len]!=c)last=last->fa;
if(!last->son[c]){
++now;
now->len=last->len+2;
point q=last->fa;
while(s[n-q->len-1]^c)q=q->fa;
now->fa=q->son[c];
if(!now->fa)now->fa=nd;
last->son[c]=now;
}
last=last->son[c];
++last->cnt;
}
inline ll calc(){
re ll ans=0;
for(point re i=now;i>nd+1;--i){
i->fa->cnt+=i->cnt;
ans=max(ans,(ll)i->cnt*i->len);
}
return ans;
}
}pam;
char s[N];int len;
signed main(){
len=fread(s+1,1,N-1,stdin);
for(int re i=1;i<len;++i)pam.push_back(s[i]);
printf("%lld",pam.calc());
return 0;
}