比赛 清华集训2017模板练习 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 找相同子串 最终得分 100
用户昵称 栋霸霸 运行时间 0.508 s
代码语言 C++ 内存使用 34.16 MiB
提交时间 2017-07-17 15:25:15
显示代码纯文本
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 200010
using namespace std;
char str[MAXN<<1];
int len[MAXN<<1],fa[MAXN<<1],trans[MAXN<<1][26],right[MAXN<<1],last,cnt,rt,n;
void Extend(int x)
{
	int p=last,np=last=++cnt;
	len[np]=len[p]+1;
	right[np]=1;
	while(p&&!trans[p][x])trans[p][x]=np,p=fa[p];
	if(!p)fa[np]=rt;
	else
	{
		int q=trans[p][x];
		if(len[p]+1==len[q])fa[np]=q;
		else
		{
			int nq=++cnt;
			len[nq]=len[p]+1;
			copy(trans[q],trans[q]+26,trans[nq]);
			fa[nq]=fa[q];
			fa[q]=fa[np]=nq;
			while(p&&trans[p][x]==q)trans[p][x]=nq,p=fa[p];
		}
	}
}
int c[MAXN<<1]= {0},a[MAXN<<1]= {0},appear[MAXN<<1]= {0};
void RadixSort()
{
	for(int i=0; i<=n; i++)c[i]=0;
	for(int i=1; i<=cnt; i++)c[len[i]]++;
	for(int i=1; i<=n; i++)c[i]+=c[i-1];
	for(int i=cnt; i>=1; i--)a[c[len[i]]--]=i;
}
long long ans=0,f[MAXN<<1]= {0};
int sb()
{
	freopen("find_2016.in","r",stdin);
	freopen("find_2016.out","w",stdout);
	scanf("%s",str+1);
	n=strlen(str+1);
	last=cnt=rt=1;
	for(int i=1; i<=n; i++)Extend(str[i]-'a');
	RadixSort();
	int u;
	for(int i=cnt; i>=1; i--)u=a[i],right[fa[u]]+=right[u];
	int le=0;
	u=rt;
	scanf("%s",str+1);
	n=strlen(str+1);
	for(int i=1; i<=n; i++)
	{
		int c=str[i]-'a';
		if(trans[u][c])le++,u=trans[u][c];
		else
		{
			while(u&&!trans[u][c])u=fa[u];
			if(!u)u=rt;
			else le=len[u]+1,u=trans[u][c];
		}
		appear[u]++,ans+=(long long)right[u]*(le-len[fa[u]]);
	}
	for(int i=cnt; i>=1; i--)u=a[i],f[fa[u]]+=f[u]+appear[u];
	for(int i=2; i<=cnt; i++)ans+=(long long)right[i]*f[i]*(len[i]-len[fa[i]]);
	printf("%lld",ans);
	return 0;
}
int chh=sb();
int main()
{
	;
}