洛谷3804

题目描述

给定一个只包含小写字母的字符串S ,

请你求出 SSS 的所有出现次数不为 1 的子串的出现次数乘上该子串长度的最大值。

输入输出格式

输入格式:

一行一个仅包含小写字母的字符串S

输出格式:

一个整数,为 所求答案

输入输出样例

输入样例#1: 复制
abab
输出样例#1: 复制
4

说明

对于10% 的数据,S<=1000

对于100% 的数据,S<=10^6

  • 拓扑排序后边更新size,边统计答案。节点size就是字符串出现次数。
  • 注意size貌似不能在ins时直接统计,可能会多一  (节点x的size  sz[x]=儿子的size之和  ,或者说是以自己为根的子树大小-1)
 1 #include<cstring>
 2 #include<cstdio>
 3 #include<iostream>
 4 const int N=3000005;
 5 int c[N][27],f[N],l[N],sz[N],you[N],dl[N],ru[N],pre=1,cnt=1,ans=0,tp=0,n;
 6 char s[N>>1];
 7 
 8 inline void ins(int x){
 9     int p=pre,np=++cnt;pre=np;you[np]=1;l[np]=l[p]+1;
10     for(;p&&!c[p][x];p=f[p])c[p][x]=np;
11     if(!p)f[np]=1;
12     else{
13         int q=c[p][x];
14         if(l[q]==l[p]+1)f[np]=q;
15         else{
16             int nq=++cnt;
17             memcpy(c[nq],c[q],sizeof(c[q]));
18             f[nq]=f[q];
19             l[nq]=l[p]+1;
20             f[q]=f[np]=nq;
21             for(;c[p][x]==q;p=f[p]) c[p][x]=nq;
22         }
23     }
24 }
25 inline void topu(){
26     for(int i=1;i<=cnt;++i)++ru[f[i]];
27     for(int i=1;i<=cnt;++i)if(!ru[i])dl[++tp]=i;
28     while(tp){
29         int p=dl[tp];--tp;
30         sz[p]+=you[p];
31         if(sz[p]>1)if(l[p]*sz[p]>ans)ans=l[p]*sz[p];
32         sz[f[p]]+=sz[p];
33         if(!(--ru[f[p]]))dl[++tp]=f[p];
34     }
35 }
36 int main(){
37     scanf("%s",s);
38     n=strlen(s);
39     for(int i=0;i<n;++i)ins(s[i]-'a');
40     topu();
41     printf("%d",ans);
42     return 0;
43 }
原文地址:https://www.cnblogs.com/xln1111/p/8619684.html