题意

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

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

对于\(100\%\) 的数据,\(|S| \leq 10^6\)

分析

后缀自动机和拓扑序的裸题。

对一个节点而言,其后每可转移到一个可接受的节点,标志着该节点对应的子串出现次数加1。

处理顺序需要可转移到的节点都被处理到,所以拓扑排序就好了。

时间复杂度\(O(|S|)\)

代码

#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#define rg register
#define il inline
#pragma GCC optimize ("O3")
using namespace std;
template<class T> inline T read(T&x)
{
    T data=0;
    int w=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        data=10*data+ch-'0',ch=getchar();
    return x=data*w;
}
typedef long long ll;
const int INF=0x7fffffff;

const int MAXN=1e6+7;
int n;
char s[MAXN];

const int CHARSET_SIZE=26;
struct node
{
    int ch[CHARSET_SIZE],fa,len;
};

struct SufAuto
{
    node t[MAXN<<1];
    int cnt[MAXN<<1];
    int sz,root,last;

    il int newnode(rg const int&x)
    {
        t[++sz].len=x;
        return sz;
    }

    il void init()
    {
        memset(cnt,0,sizeof cnt);
        sz=0;
        root=last=newnode(0);
    }

    il void extend(rg const int&c)
    {
        rg int v = last,u = newnode(t[v].len + 1);

        for(;v && !t[v].ch[c];v = t[v].fa)
            t[v].ch[c] = u;

        if(!v)
        {
            t[u].fa=root;
        }
        else
        {
            rg int o = t[v].ch[c];
            if(t[o].len == t[v].len+1)
            {
                t[u].fa = o;
            }
            else
            {
                rg int n = newnode(t[v].len + 1);
                copy(t[o].ch,t[o].ch+CHARSET_SIZE,t[n].ch);
                t[n].fa = t[o].fa;
                t[o].fa = t[u].fa = n;
                for(;v && t[v].ch[c] == o;v = t[v].fa)
                    t[v].ch[c] = n;
            }
        }

        cnt[u]=1;
        last = u;
    }

    int a[MAXN<<1],c[MAXN];
    il void rdxsort()
    {
        memset(c,0,sizeof c);
        for(rg int i=1;i<=sz;++i)
            ++c[t[i].len];
        for(rg int i=1;i<=n;++i)
            c[i]+=c[i-1];
        for(rg int i=sz;i>=1;--i)
            a[c[t[i].len]--]=i;
    }

    il int solve()
    {
        rg ll ans=0;
        for(rg int i=sz;i>=1;--i)
        {
            rg int p=a[i];
            cnt[t[p].fa]+=cnt[p];
            if(cnt[p]>1)
                ans=max(ans,(ll)cnt[p]*t[p].len);
        }
        return ans;
    }
}T;

int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    scanf("%s",s);
    n=strlen(s);
    T.init();
    for(rg int i=0;i<n;++i)
        T.extend(s[i]-'a');
    T.rdxsort();
    printf("%d\n",T.solve());
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}

LG3804 【模板】后缀自动机的更多相关文章

  1. [模板] 后缀自动机&&后缀树

    后缀自动机 后缀自动机是一种确定性有限状态自动机, 它可以接收字符串\(s\)的所有后缀. 构造, 性质 翻译自毛子俄罗斯神仙的博客, 讲的很好 后缀自动机详解 - DZYO的博客 - CSDN博客 ...

  2. Luogu3804:[模板]后缀自动机

    题面 luogu Sol \(sam\)然后树形\(DP\) 当时还不会拓扑排序的我 # include <bits/stdc++.h> # define IL inline # defi ...

  3. 洛谷 P3804 [模板] 后缀自动机

    题目:https://www.luogu.org/problemnew/show/P3804 模仿了一篇题解,感觉很好写啊. 代码如下: #include<cstdio> #include ...

  4. SPOJ LCS Longest Common Substring 和 LG3804 【模板】后缀自动机

    Longest Common Substring 给两个串A和B,求这两个串的最长公共子串. no more than 250000 分析 参照OI wiki. 给定两个字符串 S 和 T ,求出最长 ...

  5. 【Luogu3804】【模板】后缀自动机(后缀自动机)

    [Luogu3804][模板]后缀自动机(后缀自动机) 题面 洛谷 题解 一个串的出现次数等于\(right/endpos\)集合的大小 而这个集合的大小等于所有\(parent\)树上儿子的大小 这 ...

  6. 字符串数据结构模板/题单(后缀数组,后缀自动机,LCP,后缀平衡树,回文自动机)

    模板 后缀数组 #include<bits/stdc++.h> #define R register int using namespace std; const int N=1e6+9; ...

  7. P3804 【模板】后缀自动机

    P3804 [模板]后缀自动机 后缀自动机模板 详情可见luogu题解板块 #include<iostream> #include<cstdio> #include<cs ...

  8. 2018.07.17 后缀自动机模板(SAM)

    洛谷传送门 这是一道后缀自动机的模板题,这道题让我切身体会到了后缀自动机的方便与好写. 代码如下: #include<bits/stdc++.h> #define N 2000005 #d ...

  9. 牛客网 桂林电子科技大学第三届ACM程序设计竞赛 A.串串-后缀自动机模板题

    链接:https://ac.nowcoder.com/acm/contest/558/A来源:牛客网 A.串串 小猫在研究字符串. 小猫在研究字串. 给定一个长度为N的字符串S,问所有它的子串Sl…r ...

随机推荐

  1. jsp/servlet区别

    简介: JSP全名为Java Server Pages,中文名叫java服务器页面,其根本是一个简化的Servlet设计,它是由Sun Microsystems公司倡导.许多公司参与一起建立的一种动态 ...

  2. php时区设置 warning: strtotime(): It is not safe to rely on the system's timezone settings

    warning: strtotime(): It is not safe to rely on the system's timezone settings warning: strtotime(): ...

  3. FMUtils.KeyboardHook 轻量级键盘监听器

    Nuget添加引用 Install-Package FMUtils.KeyboardHook 调用示例: var KeyboardHook = new Hook("Global Action ...

  4. 正睿 2019 省选附加赛 Day1 T1 考考试

    比较奇怪的一个枚举题. 注意到10=2*5,所以10^k的二进制表示一定恰好在末尾有k个0. 考虑从小到大去填这个十进制数. 填的时候记录一下当前的二进制表示. 每次尝试去填0或者10^k. 如果要填 ...

  5. 解决导入Gradle项目遇到的问题

    Gradle安装好了,插件也在eclipse中配置好了,却不会导入,尴尬.这里我就给大家介绍几个在配置 导入项目所遇到的问题: 分别选择Browse选中本地目录,和BuildModel创建相关的项目文 ...

  6. python-day12--函数进阶

    1.命名空间: 分三种:全局命名空间,局部命名空间,内置命名空间. 加载顺序:内置命名空间→全局命名空间→局部命名空间 取值顺序:局部命名空间→全局命名空间→内置命名空间 2.作用域: 作用域就是作用 ...

  7. OAF中多语言的实现(转)

    正好前两天研究过这个问题,分享一下啊. 标题:        OAF中多语言的实现概述:        OAF的多语言的实现有两种方式,其一是直接通过页面上面的“个性化”连接,连接到指定的页面后,进行 ...

  8. ThreadPoolExecutor类

    首先分析内部类:ThreadPoolExecutor$Worker //Worker对线程和任务做了一个封装,同时它又实现了Runnable接口, //所以Worker类的线程跑的是自身的run方法 ...

  9. 使用iview-project 打包build报错,ERROR in xxxxx.cheunk.js from UglifyJs

    一.iview-project  为iview官方推荐工程,一个基于iview的vue脚手架 github网址:https://github.com/iview/iview-project 废话不多说 ...

  10. SQL Server 自动化运维系列 - 监控磁盘剩余空间及SQL Server错误日志(Power Shell)

    需求描述 在我们的生产环境中,大部分情况下需要有自己的运维体制,包括自己健康状态的检测等.如果发生异常,需要提前预警的,通知形式一般为发邮件告知. 在所有的自检流程中最基础的一个就是磁盘剩余空间检测. ...