比赛 清华集训2017模板练习 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 找相同子串 最终得分 100
用户昵称 Cydiater 运行时间 0.625 s
代码语言 C++ 内存使用 51.43 MiB
提交时间 2017-07-17 15:08:29
显示代码纯文本
#include <bits/stdc++.h>

using namespace std;

#define ll long long
#define up(i,j,n)	for(int i=j;i<=n;i++)
#define down(i,j,n)	for(int i=j;i>=n;i--)
#define cmax(a,b)	a=max(a,b)
#define cmin(a,b)	a=min(a,b)
#define FILE		"find_2016"

const int MAXN=4e5+5;
const int oo=0x3f3f3f3f;

int N,M;
char s[MAXN],t[MAXN];
ll ans=0,LEN=0;

namespace SAM{
	int p,q,np,nq,step[MAXN],pre[MAXN],son[MAXN][26],root=1,cnt=1;
	int mark[MAXN],rnk[MAXN],R[MAXN],now=1;
	ll con[MAXN];
	void extend(int nxt){
		p=now;now=np=++cnt;
		step[np]=step[p]+1;
		R[np]=1;
		for(;p&&!son[p][nxt];p=pre[p])son[p][nxt]=np;
		if(!p)pre[np]=root;
		else{
			q=son[p][nxt];
			if(step[q]==step[p]+1)pre[np]=q;
			else{
				step[nq=++cnt]=step[p]+1;
				memcpy(son[nq],son[q],sizeof(son[nq]));
				pre[nq]=pre[q];
				pre[np]=pre[q]=nq;
				for(;son[p][nxt]==q;p=pre[p])son[p][nxt]=nq;
			}
		}
	}
	void Topsort(){
		up(i,1,cnt)mark[step[i]]++;
		up(i,1,N)mark[i]+=mark[i-1];
		down(i,cnt,1)rnk[mark[step[i]]--]=i;
		down(i,cnt,1){
			int node=rnk[i];
			R[pre[node]]+=R[node];
		}
		up(i,1,cnt){
			int node=rnk[i];
			con[node]=con[pre[node]]+R[node]*(step[node]-step[pre[node]]);
		}
	}
	void Go(int nxt){
		if(!now)now=root;
		while(!son[now][nxt]){
			now=pre[now];
			LEN=step[now];
		}
		if(son[now][nxt]){
			now=son[now][nxt];
			LEN++;
			ans+=con[pre[now]]+1LL*(LEN-step[pre[now]])*R[now];
		}
	}
}using namespace SAM;

namespace solution{
	void Solve(){
		scanf("%s%s",s+1,t+1);
		N=strlen(s+1);M=strlen(t+1);
		up(i,1,N)extend(s[i]-'a');
		Topsort();
		now=root;
		up(i,1,M)Go(t[i]-'a');
		cout<<ans<<endl;
	}
}

int main(){
	freopen(FILE".in","r",stdin);
	freopen(FILE".out","w",stdout);
	using namespace solution;
	Solve();
	return 0;
}