spoj 1811 lcs

題目大意:就是給你兩個串,然後求最長公共子串, 串長<=250000 ,但是spoj太慢了,所以要O(N)

這題就是後綴自動機的裸題

先以第一個串做一個自動機,在用第二個串去匹配,就有點想kmp的感覺,不能匹配就往前跳

#include<cmath>
#include<cstdio>
#include<cstring>
#include<cassert>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=250011;
struct Tsam{
	struct Tnode{
		Tnode *ch[26],*f; int ml;
		void clear(){memset(ch,0,sizeof(ch)); ml=0; f=NULL;}
	}e[maxn<<1],*root,*last;
	int tot;
	Tnode *newnode(){e[tot].clear(); return e+(tot++);}
	void clear(){tot=0; root=last=newnode();}
	void add(int c){
		Tnode *np=newnode(),*p=last; np->ml=last->ml+1;
		for (last=np;p && !p->ch[c];p=p->f) p->ch[c]=np;
		if (!p) return np->f=root,void();
		Tnode *q=p->ch[c];
		if (q->ml==p->ml+1) return np->f=q,void();
		Tnode *r=newnode(); *r=*q;
		r->ml=p->ml+1; q->f=np->f=r;
		for (;p && p->ch[c]==q;p=p->f) p->ch[c]=r;
	}
}sam;
char s1[maxn],s2[maxn]; int n,m;
void init(){scanf("%s%s",s1,s2);}
void work(){
	sam.clear(); n=strlen(s1); m=strlen(s2);
	for (int i=0;i<n;++i) sam.add(s1[i]-'a');
	for (int i=0;i<m;++i) s2[i]-='a';
	Tsam::Tnode *now=sam.root; int res=0,ans=0;
	for (int i=0;i<m;++i){
		if (now->ch[s2[i]]) ++res,now=now->ch[s2[i]];
		else{
			for (;now && !now->ch[s2[i]];now=now->f);
			if (!now) now=sam.root,res=0;
			else res=now->ml+1,now=now->ch[s2[i]];
		}
		if (res>ans) ans=res;
	}
	printf("%d\n",ans);
}
int main(){
	init();
	work();
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章