题目描述
输出在字符串s中出现超过1次的子串长度乘以它的出现次数
分析
容易想到记录节点size值建出Parent树暴力跑DFS统计
#include <iostream>
#include <cstring>
#include <cstdio>
#define rep(i,a,b) for (i=a;i<=b;i++)
const int N=1e6;
using namespace std;
struct Edge {
int u,v,nx;
}g[4*N];
int cnt,list[2*N];
struct Node {
int len,link,sz;
int c[26];
}s[2*N];
int sz,last;
bool b[2*N];
long long ans;
void Extend(char c) {
int cur=++sz;
s[cur].len=s[last].len+1;s[cur].sz=1;
int p;
for (p=last;p!=-1&&!s[p].c[c-'a'];p=s[p].link)
s[p].c[c-'a']=cur;
last=cur;
if (p==-1) {
s[cur].link=0;
return;
}
int q=s[p].c[c-'a'];
if (s[q].len==s[p].len+1) {
s[cur].link=q;
return;
}
int clone=++sz;
s[clone]=s[q];
s[clone].sz=0;
s[clone].len=s[p].len+1;
s[cur].link=s[q].link=clone;
for (;p!=-1&&s[p].c[c-'a']==q;p=s[p].link) s[p].c[c-'a']=clone;
}
void Dfs(int u) {
b[u]=1;
for (int i=list[u];i;i=g[i].nx)
if (!b[g[i].v]) {
Dfs(g[i].v);
s[u].sz+=s[g[i].v].sz;
}
if (s[u].sz>1) ans=max(ans,1ll*s[u].sz*s[u].len);
}
int main() {
string ss;
int i;
cin>>ss;
s[0].link=-1;
rep(i,0,ss.length()-1) Extend(ss[i]);
rep(i,1,sz)
{g[++cnt].u=s[i].link;g[cnt].v=i;g[cnt].nx=list[s[i].link];list[s[i].link]=cnt;}
Dfs(0);
printf("%lld",ans);
}