●POJ 2774 Long Long Message

题链:

http://poj.org/problem?id=2774
题解:

后缀自动机
使用后缀自动机匹配,思路如下:
即如果当前的x字符匹配失败了,就可以从当前已经匹配的串的后缀去继续匹配。
然后不难发现,对于失配的状态s的parent[s]恰好是可能能够继续匹配x且Right集合是最小的包含s的Right集合(即允许的合法长度除了s外是最长的)的状态。
所以就沿着parent指针向上跳,直到trans[*][x]存在或者到了0号节点。


代码:

 

#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 250005
using namespace std;
struct SAM{
	int size,last;
	int maxs[MAXN*5],trans[MAXN*5][26],parent[MAXN*5];
	int Newnode(int a,int b){
		maxs[size]=a;
		memcpy(trans[size],trans[b],sizeof(trans[b]));
		return size++;
	}
	void Extend(int x){
		static int p,np,q,nq;
		p=last; last=np=Newnode(maxs[p]+1,0);
		for(;p&&!trans[p][x];p=parent[p]) trans[p][x]=np;
		if(!p) parent[np]=1;
		else{
			q=trans[p][x];
			if(maxs[p]+1!=maxs[q]){
				nq=Newnode(maxs[p]+1,q);
				parent[nq]=parent[q];
				parent[q]=parent[np]=nq;
				for(;p&&trans[p][x]==q;p=parent[p]) trans[p][x]=nq;
			}
			else parent[np]=q;
		}
	}
	void Build(char *S){
		memset(trans[0],0,sizeof(trans[0]));
		size=1; last=Newnode(0,0);
		for(int i=0;S[i];i++) Extend(S[i]-'a');
	}
	int Match(char *T){
		int p=1,i=0,ans=0,now=0,len=strlen(T);
		while(i<len){
			if(p&&!trans[p][T[i]-'a']){
				ans=max(ans,min(now,maxs[p]));
				p=parent[p]; now=maxs[p];
			}
			else if(p) now++,p=trans[p][T[i]-'a'],i++;
			else i++,p=1;
		}
		return max(ans,min(now,maxs[p]));
	}
}SUF;
int main(){
	char S[MAXN];
	scanf("%s",S);
	SUF.Build(S);
	scanf("%s",S);
	int ans=SUF.Match(S);
	printf("%d\n",ans);
	return 0;
}

 

  

 

posted @ 2018-03-10 20:35  *ZJ  阅读(115)  评论(0编辑  收藏  举报