Description
考虑一个只包含小写拉丁字母的字符串s。我们定义s的一个子串t的“出
现值”为t在s中的出现次数乘以t的长度。请你求出s的所有回文子串中的最
大出现值。
Input
输入只有一行,为一个只包含小写字母(a -z)的非空字符串s。
Output
输出一个整数,为回文子串的最大出现值。
Sample Input
abacaba
Sample Output
7
Solution
SA+manacher。
考虑(manacher)的过程中,本质不同的回文串只会在每次扩展的时候出现,所以每次扩展的时候上下二分,然后算一下就好了。
复杂度(O(nlog n))。
注意(manacher)之前会把原串翻倍,在翻倍之前就把(sa)建好,否则卡不过。。
(其实这题正解是回文自动机来着。。那玩意貌似是O(n)的)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
#define ll long long
void print(ll x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(ll x) {if(!x) putchar('0');else print(x);putchar('
');}
const int maxn = 6e5+10;
char c[maxn],s[maxn];
int n,f[maxn];
ll ans;
int spx[maxn],spy[maxn],sum[maxn],sa[maxn],m,rk[maxn],height[maxn],st[maxn][20],lg[maxn],len;
void get_sa() {
m=240;int p=0,*x=spx,*y=spy;
for(int i=1;i<=n;i++) sum[x[i]=c[i]]++;
for(int i=1;i<=m;i++) sum[i]+=sum[i-1];
for(int i=n;i;i--) sa[sum[x[i]]--]=i;
for(int tot=0,k=1;p<n;k<<=1,tot=0) {
p=0;
for(int i=n-k+1;i<=n;i++) y[++tot]=i;
for(int i=1;i<=n;i++) if(sa[i]>k) y[++tot]=sa[i]-k;
for(int i=1;i<=m;i++) sum[i]=0;
for(int i=1;i<=n;i++) sum[x[y[i]]]++;
for(int i=1;i<=m;i++) sum[i]+=sum[i-1];
for(int i=n;i;i--) sa[sum[x[y[i]]]--]=y[i];
swap(x,y);x[sa[1]]=p=1;
for(int i=2;i<=n;i++)
if(y[sa[i]]!=y[sa[i-1]]||y[sa[i]+k]!=y[sa[i-1]+k]) x[sa[i]]=++p;
else x[sa[i]]=p;
m=n;
}
}
void get_height() {
for(int i=1;i<=n;i++) rk[sa[i]]=i;
int p=1;
for(int i=1;i<=n;i++) {
if(p) p--;
while(c[i+p]==c[sa[rk[i]-1]+p]) p++;
height[rk[i]]=p;
}
}
void rmq_init() {
for(int i=1;i<=n;i++) st[i][0]=height[i];
for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1;
for(int i=1;i<=18;i++)
for(int j=1;j<=n;j++)
st[j][i]=min(st[j][i-1],st[j+(1<<(i-1))][i-1]);
}
int get_rmq(int l,int r) {
if(r<l) return r=l;
int w=lg[r-l+1];
return min(st[l][w],st[r-(1<<w)+1][w]);
}
void get_ans(int lpos,int rpos,int xx) {
if(s[lpos]=='&') return ;
lpos/=2,rpos/=2;
int w=rk[lpos];
int l=1,r=w,ret=w,mid,Len=rpos-lpos+1;
while(l<=r) {
mid=(l+r)>>1;
if(get_rmq(mid+1,w)>=Len) ret=mid,r=mid-1;
else l=mid+1;
}
int ret2=w;l=w,r=len;
while(l<=r) {
mid=(l+r)>>1;
if(get_rmq(w+1,mid)>=Len) ret2=mid,l=mid+1;
else r=mid-1;
}
ans=max(ans,1ll*(ret2-ret+1)*xx);
}
int main() {
char e=getchar();
while(e!=EOF&&e!='
') c[++len]=e,e=getchar();
n=len;get_sa(),get_height(),rmq_init();
s[n=0]='$',s[++n]='&';
for(int i=1;i<=len;i++) s[++n]=c[i],s[++n]='&';
int mr=1,mid=1;
for(int i=1;i<=n;i++) {
f[i]=min(mr-i,f[mid*2-i]);
while(s[i-f[i]]==s[i+f[i]]) get_ans(i-f[i],i+f[i],f[i]+1),f[i]++;
if(i+f[i]>mr) mr=i+f[i],mid=i;
}
write(ans);
return 0;
}