10分 初学SAM 求大佬帮忙调调板子题 QAQ
查看原帖
10分 初学SAM 求大佬帮忙调调板子题 QAQ
335552
Christophe_楼主2022/7/3 19:14
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=8e6+10;
struct SAM{
	static const int sam_maxn=4e5+10,maxc=26,rt=1;
	static const char min_char='a';
	int trans[sam_maxn<<1][maxc],fa[maxn],maxL[maxn];
	int lst,cnt;
	int num[maxn];
	int fa_topo[maxn],cntL[maxn];
	SAM(){ clear(); }
	void clear(){
		lst=cnt=rt;
		fa[rt]=0,maxL[rt]=0;
	}
	void build(char *s){
		for(int i=0;s[i];++i) extend(s[i]-min_char);
	}
	void extend(int c){
		int p=lst,np=++cnt;
		lst=np;
		memset(trans[np],0,sizeof(trans[np]));
		maxL[np]=maxL[p]+1;
		while(p&&trans[p][c]==0) trans[p][c]=np,p=fa[p];
		if(p==0){
			fa[np]=rt;
			return;
		}
		int q=trans[p][c];
		if(maxL[q]==maxL[p]+1) fa[np]=q;
		else{
			int nq=++cnt;
			fa[np]=nq;
			memcpy(trans[nq],trans[q],sizeof(trans[q]));
			maxL[nq]=maxL[p]+1;
			fa[nq]=fa[q],fa[q]=nq;
			while(trans[p][c]==q) trans[p][c]=nq,p=fa[p];
		}
	}
	void get_right_topo(){
		for(int i=rt;i<=cnt;++i) ++cntL[maxL[i]];
		for(int i=rt;i<=cnt;++i) cntL[i]=cntL[i-1]+cntL[i];
		for(int i=cnt;i>=rt;--i) fa_topo[cntL[maxL[i]]--]=i;
	}
	LL get_ans(char *s){
		get_right_topo();
		LL ans=0;
		int tmp=rt;
		for(int i=0;s[i];++i){
			int c=s[i]-min_char;
			tmp=trans[tmp][c],num[tmp]=1;
		}
		for(int i=cnt;i>=rt;--i){
			int x=fa_topo[i];
			num[fa[x]]+=num[x];
			if(num[x]!=1) ans=max(ans,(LL)maxL[x]*num[x]);
		}
		return ans;
	}
};
SAM sam;
char S[maxn];
int main(){
	scanf("%s",S);
	sam.build(S);
	printf("%lld",sam.get_ans(S));
}

RT, 除了 #1 ,其他全 WA 掉了qwqqwq

2022/7/3 19:14
加载中...