LGOJ3804 【模板】后缀自动机

题目链接:

link

题目大意

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

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

Solution

预处理出每个节点中的子串在原串中出现的次数 \(f[i]\)

我们枚举每个节点,对于每个节点,如果其 \(f[i]\) 不为 \(1\) ,则求其 \(t[i]=f[i]\times len(i)\)

\(t[i] _ {max}\)即为答案

CODE

#include
using namespace std;
#define int long long
#define reg register
namespace yspm{
	inline int read()
	{
		int res=0,f=1; char k;
		while(!isdigit(k=getchar())) if(k=='-') f=-1;
		while(isdigit(k)) res=res*10+k-'0',k=getchar(); 
		return res*f;
	}
	const int N=2e6+10;
	int tot=1,las=1,head[N],cnt,val[N];
	struct edge{int to,nxt;}e[N];
	struct node{
		int ch[26],len,fa;
		node(){memset(ch,0,sizeof(ch)); len=fa=0; return ;}
	}p[N];
	inline void adde(int u,int v)
	{
		e[++cnt].nxt=head[u]; e[cnt].to=v; return head[u]=cnt,void();
	}
	inline void addp(int x)
	{
		int tmp=las,np=las=++tot; val[tot]=1; p[np].len=p[tmp].len+1;
		for(;tmp&&!p[tmp].ch[x];tmp=p[tmp].fa) p[tmp].ch[x]=np;
		if(!tmp) p[np].fa=1;
		else 
		{
			int q=p[tmp].ch[x];
			if(p[q].len==p[tmp].len+1) p[np].fa=q;
			else 
			{
				int nq=++tot;
				p[nq]=p[q]; p[nq].len=p[tmp].len+1;
				p[q].fa=p[np].fa=nq;
				for(;tmp&&p[tmp].ch[x]==q;tmp=p[tmp].fa) p[tmp].ch[x]=nq;
			}
		}
		return ;
	}
	char s[N]; int len,ans;
	inline void dfs(int x)
	{
		for(reg int i=head[x];i;i=e[i].nxt)
		{
			dfs(e[i].to); val[x]+=val[e[i].to];
		}
		if(val[x]!=1) ans=max(ans,val[x]*p[x].len); 
		return ;
	}
	signed main()
	{
		scanf("%s",s); len=strlen(s);
		for(reg int i=0;i

你可能感兴趣的:(LGOJ3804 【模板】后缀自动机)