SPOJ 1811 Longest Common Substring

Description

给出两个字符串,求最长公共子串.

Sol

SAM.

这题随便做啊...后缀数组/Hash+二分都可以.

SAM就是模板啊...直接在SAM上跑就行,没有了 (go[w]) 就往 (par) 跳.

每走一步统计一下答案.

Code

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;

const int N = 250005;

struct State{
	State *par,*go[26];
	int val;
	State(int _val):par(0),val(_val){ memset(go,0,sizeof(go)); }
}*rt,*lst;
void extend(int w){
	State *p=lst,*np=new State(p->val+1);
	while(p && p->go[w]==0) p->go[w]=np,p=p->par;
	if(!p) np->par=rt;
	else{
		State *q=p->go[w];
		if(q->val == p->val+1) np->par=q;
		else{
			State *nq=new State(p->val+1);
			memcpy(nq->go,q->go,sizeof(q->go));
			nq->par=q->par;
			np->par=q->par=nq;
			while(p && p->go[w] == q) p->go[w]=nq,p=p->par;
		}
	}lst=np;
}

char A[N],B[N];
int la,lb,ans,len;

void work(){
	State *t=rt;
	for(int i=0;i<lb;i++){
		for(;t && !t->go[B[i]-'a'];len=(t=t->par) ? t->val : 0);
		if(t && t->go[B[i]-'a']) t=t->go[B[i]-'a'],len++;else t=rt;
		ans=max(ans,len);
	}
}
int main(){
	rt=new State(0),lst=rt;
	
	scanf("%s%s",A,B);
	la=strlen(A),lb=strlen(B);
	
	for(int i=0;i<la;i++) extend(A[i]-'a');
	
	work();
	return cout<<ans<<endl,0;
}

  

原文地址:https://www.cnblogs.com/beiyuoi/p/5954222.html