首页 > 代码库 > SPOJ 1811 Longest Common Substring

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;}

  

SPOJ 1811 Longest Common Substring