• ●SPOJ LCS2Longest Common Substring II


    题链:

    http://www.spoj.com/problems/LCS2/
    题解:

    后缀自动机。
    对第一个串建立后缀自动机,
    然后把后面的每个串分别与该串的自动机去匹配,求出相应的数组val*[s]:
    表示第*个串与第一个串的自动机的状态s的最大匹配长度,

    (求法就是两个串用后缀自动机求LCS这一过程):
    对于当前已经匹配的子串T,长度为now,此刻在状态s,现在要匹配第i个字符x,
    若trans(s,x)!=0,则s=trans(s,x),now++,i++,并更新val*[s]=max(val*[s],now);
    否则,s=parent[s],直到trans(s,x)!=0或者s=0。
    由于我们在每一步更新s时,没有更新到其祖先,所以最后再桶排之后去依次更新父亲。

    而最后的状态s和每个串的最大匹配长度就是min(min(val*[s]),maxs[s](这个是状态s所允许的最大长度));


    代码:

    #include<bits/stdc++.h>
    #define MAXN 100005
    #define INF 0x3f3f3f3f
    using namespace std;
    struct SAM{
    	int size,last,lens;
    	int maxs[MAXN*3],trans[MAXN*3][26],parent[MAXN*3],minmatch[MAXN*3];
    	int Newnode(int a,int b){
    		++size; maxs[size]=a; minmatch[size]=INF;
    		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=0; last=Newnode(0,0); lens=strlen(S);
    		for(int i=0;i<lens;i++) Extend(S[i]-'a');
    	}
    	void Update(int *val){
    		static int tmp[MAXN],order[MAXN*3];
    		memset(tmp,0,sizeof(tmp));
    		for(int p=1;p<=size;p++) tmp[maxs[p]]++;
    		for(int i=1;i<=lens;i++) tmp[i]+=tmp[i-1];
    		for(int p=1;p<=size;p++) order[tmp[maxs[p]]--]=p;
    		for(int i=size,p;i;i--)
    			p=order[i],val[parent[p]]=max(val[parent[p]],val[p]);
    	}
    	void Match(char *T){
    		static int val[MAXN*3],p,i,len,now;
    		for(p=1;p<=size;p++) val[p]=0;
    		p=1; i=0; now=0; len=strlen(T);
    		while(i<len){
    			if(!p) p=1,now=0,i++;
    			else if(!trans[p][T[i]-'a']) p=parent[p],now=maxs[p];
    			else now++,p=trans[p][T[i]-'a'],i++;
    			val[p]=max(val[p],now);
    		}
    		Update(val);
    		for(p=1;p<=size;p++) minmatch[p]=min(minmatch[p],val[p]);
    	}
    }SUF;
    int main(){
    	static char S[MAXN];
    	scanf("%s",S); SUF.Build(S);
    	while(~scanf("%s",S)) SUF.Match(S);
    	int ans=0;
    	for(int p=1;p<=SUF.size;p++)
    		ans=max(ans,min(SUF.minmatch[p],SUF.maxs[p]));
    	printf("%d
    ",ans);
    	return 0;
    }
    

      

  • 相关阅读:
    MyEclipse去除网上复制下来的代码带有的行号
    Python人工智能第二篇
    Celery
    SQLAlchemy介绍
    MongoDB
    第三篇 Flask 中的 request
    linux安装
    第二篇 Flask 中的 Render Redirect HttpResponse
    第九篇 Flask 中的蓝图(BluePrint)
    第一篇 Flask
  • 原文地址:https://www.cnblogs.com/zj75211/p/8541876.html
Copyright © 2020-2023  润新知