1. 程式人生 > 實用技巧 >Luogu4248 [AHOI2013]差異

Luogu4248 [AHOI2013]差異

https://www.luogu.com.cn/problem/P4248

字尾自動機

觀察原式,類似樹上兩點間距離

顯然,這棵樹是\(Parent\)

那麼,跑一遍\(dfs\)即可

\(C++ Code:\)

#include<bits/stdc++.h>
#define N 1000005
#define M 1500005
using namespace std;
int tot,head[M],d[M],d2[M],nxt[M],sz[M];
int t[N][26],pre[N],len[N];
int n,cnt=1,last=1;
long long ans=0;
char s[N],s1[N];
void ins(int c)
{
	int p,q;
	int np=++cnt;
	sz[np]=1;
	len[np]=len[last]+1;
	for (p=last;p&&!t[p][c];p=pre[p])
		t[p][c]=np;
	if (!p)
		pre[np]=1; else
		{
			q=t[p][c];
			if (len[p]+1==len[q])
				pre[np]=q; else
				{
					int g=++cnt;
					len[g]=len[p]+1;
					for (int i=0;i<26;i++)
						t[g][i]=t[q][i];
					pre[g]=pre[q];
					for (;p&&t[p][c]==q;p=pre[p])
						t[p][c]=g;
					pre[q]=pre[np]=g;
				}
		}
	last=np;
}
void add(int x,int y,int z)
{
	tot++;
	d[tot]=y;
	d2[tot]=z;
	nxt[tot]=head[x];
	head[x]=tot;
}
void dfs(int u)
{
	for (int i=head[u];i;i=nxt[i])
	{
		int v=d[i];
		int v2=d2[i];
		dfs(v);
		ans+=(long long)sz[v]*(n-sz[v])*v2;
		sz[u]+=sz[v];
	}
}
int main() 
{
	scanf("%s",s);
	n=strlen(s);
	for (int i=1;i<=n;i++)
		s1[i-1]=s[n-i];
	for (int i=0;i<n;i++)
		ins(s1[i]-'a');
	for (int i=2;i<=cnt;i++)
		add(pre[i],i,len[i]-len[pre[i]]);
	dfs(1);
    cout << ans << endl;
	return 0;
}