【SPOJ】【P1811】【LCS】【题解】【SAM】

传送门:http://www.spoj.com/problems/LCS/

Q:后缀数组背不过怎么办?

A:背后缀自动机啊

蒟蒻的SAM第一弹

Code:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=250010;
struct node{
	int val;
	node *pre,*go[26];
	node(int _val=0):
		val(_val),pre(0){
			memset(go,0,sizeof go);
		}
}*root,*last,pool[maxn<<1];
node *newnode(int val){
	static int tot=0;
	if(tot<(maxn<<1)){pool[tot].val=val;return &pool[tot++];}
	return new node(val);
}
void push(int x){
	node *p=last,*np=newnode(p->val+1);
	while(p&&p->go[x]==0)p->go[x]=np,p=p->pre;
	if(!p)np->pre=root;
	else{
		node *q=p->go[x];
		if(p->val+1==q->val)np->pre=q;
		else{
			node *nq=newnode(p->val+1);
			memcpy(nq->go,q->go,sizeof q->go);
			nq->pre=q->pre;
			q->pre=np->pre=nq;
			while(p&&p->go[x]==q)p->go[x]=nq,p=p->pre;
		}
	}last=np;
}
char s[maxn];
int len1,len2;
int main(){
	root=last=newnode(0);
	scanf("%s",s);
	len1=strlen(s);
	for(int i=0;i<len1;i++)push(s[i]-'a');
	scanf("%s",s);
	len2=strlen(s);
	int ans=0,tmp=0;
	node *p=root;
	for(int i=0;i<len2;i++){
		int x=s[i]-'a';
		if(p->go[x]){
			p=p->go[x];
			tmp++;
		}else{
			while(p&&!p->go[x])p=p->pre;
			if(p){
				tmp=p->val+1;
				p=p->go[x];
			}else{
				p=root;
				tmp=0;
			}
		}ans=max(ans,tmp);
	}cout<<ans<<endl;
	return 0;
}


你可能感兴趣的:(spoj)