1. 程式人生 > 其它 >SP1811 LCS最長公共子串 題解

SP1811 LCS最長公共子串 題解

題面

給一個串建 SAM,另一個串在上面跑。

點選檢視程式碼
const int N=2.5e5+13;
char s[N],t[N];
int nxt[N<<1],len[N<<1],ptot=1,lastpos=1;
std::unordered_map<int,int> son[N<<1],boom;
inline int newpos(std::unordered_map<int,int> nson,int nlen){return len[++ptot]=nlen,std::swap(son[ptot],nson),ptot;}
inline void insert(int c){
	int p=lastpos;int u=newpos(boom,len[p]+1);
	while(p&&son[p].find(c)==son[p].end()) son[p][c]=u,p=nxt[p];
	lastpos=u;
	if(!p) return nxt[u]=1,void();
	int d=son[p][c];
	if(len[d]==len[p]+1) nxt[u]=d;
	else{
		int v=newpos(son[d],len[p]+1);
		nxt[v]=nxt[d],nxt[d]=nxt[u]=v;
		while(p&&son[p][c]==d) son[p][c]=v,p=nxt[p];
	}
}
int main(){
	read(s+1),read(t+1);
	int n=strlen(s+1),m=strlen(t+1);
	for(int i=1;i<=n;++i) insert(s[i]-'a');
	int i=1,p=1,now=0,ans=0;
	while(i<=m){
		int c=t[i]-'a';
		while(p!=1&&son[p].find(c)==son[p].end()) p=nxt[p],now=len[p];
		if(son[p].find(c)!=son[p].end()) p=son[p][c],++now;
		chkmax(ans,now);
		++i;
	}
	println(ans);
	return 0;
}