zoukankan      html  css  js  c++  java
  • [Luogu3804]【模板】后缀自动机

    luogu

    题目描述

    给定一个只包含小写字母的字符串(S) ,
    请你求出(S)的所有出现次数不为(1)的子串的出现次数乘上该子串长度的最大值。

    sol

    “出现次数大于(1)”也就是(endpos)集合大小大于(1)
    所以可以直接上基数排序求每个状态的(endpos)集合大小。
    (我可能比较无聊建了一棵树出来跑dfs)

    code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N = 2e6+5;
    int n,last=1,tot=1,tr[N][26],fa[N],len[N],sz[N];
    int to[N],nxt[N],head[N],cnt;
    char s[N];long long ans;
    void extend(int c)
    {
    	int v=last,u=++tot;last=u;
    	len[u]=len[v]+1;
    	while (v&&!tr[v][c]) tr[v][c]=u,v=fa[v];
    	if (!v) fa[u]=1;
    	else
    	{
    		int x=tr[v][c];
    		if (len[x]==len[v]+1) fa[u]=x;
    		else
    		{
    			int y=++tot;
    			memcpy(tr[y],tr[x],sizeof(tr[y]));
    			fa[y]=fa[x];fa[x]=fa[u]=y;len[y]=len[v]+1;
    			while (v&&tr[v][c]==x) tr[v][c]=y,v=fa[v];
    		}
    	}
    	sz[u]=1;
    }
    void link(int u,int v){to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;}
    void dfs(int u)
    {
    	for (int e=head[u];e;e=nxt[e])
    		dfs(to[e]),sz[u]+=sz[to[e]];
    	if (sz[u]>1) ans=max(ans,1ll*sz[u]*len[u]);
    }
    int main()
    {
    	scanf("%s",s+1);n=strlen(s+1);
    	for (int i=1;i<=n;++i) extend(s[i]-'a');
    	for (int i=2;i<=tot;++i) link(fa[i],i);
    	dfs(1);printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    SpringBoot Mybatis的驼峰命名
    设计模式之单例模式
    Java调用TSC打印机进行打印
    DOM与Jquery方法对照表(versions:Itcast)
    jQuery选择器过滤器
    算法的力量转自李开复
    源码中的相对路径和绝对路径
    C语言I博客作业03
    firstprogram
    C语言I博客作业02
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8660220.html
Copyright © 2011-2022 走看看