zoukankan      html  css  js  c++  java
  • SPOJ1811 LCS

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

    本文作者:ljh2000
    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

    题目链接:SPOJ1811

    正解:后缀自动机

    解题报告:

      听说这道题是后缀自动机基础题和经典做法…

      把第一个串的$SAM$构出来,然后用后面那个串在上面跑匹配。

      我对于第二个串,我相当于是每次加入一个字符,如果上次在$SAM$上的匹配节点存在这样一条边就可以往下走,否则就往上跳$parent$。

      考虑这样做的正确性,因为我对于第二个串来说,如果失配了,就说明当前的左端点开始的所有情况被我考虑完了,因为之前的已经$update$了答案,而当前已经失配,再往右显然无效,所以左端点可以后移了。

      只要考虑后面的点开始的一段子串的匹配情况了。

      我每次在$parent$树上跳,相当于是砍掉了一段前缀(第一个串、第二个串同时砍),直到匹配上为止(砍掉的部分不可能成为答案了,要么已经$update$过了)。

    //It is made by ljh2000
    //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <ctime>
    #include <vector>
    #include <queue>
    #include <map>
    #include <set>
    #include <string>
    #include <complex>
    #include <bitset>
    using namespace std;
    typedef long long LL;
    typedef long double LB;
    typedef complex<double> C;
    const double pi = acos(-1);
    const int MAXN = 500011;
    int n,m,cnt,S,last,ch[MAXN][26],a[MAXN],len[MAXN],fa[MAXN],ans,L;
    char s[MAXN];
    
    inline int getint(){
        int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
        if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
    }
    
    inline void add(int x){
    	int c=a[x],p=last,np=++cnt; last=cnt;
    	len[np]=x; for(;p && !ch[p][c];p=fa[p]) ch[p][c]=np;
    	if(!p) fa[np]=S;
    	else {
    		int q=ch[p][c];
    		if(len[q]==len[p]+1) fa[np]=q;
    		else {
    			int nq=++cnt; len[nq]=len[p]+1;
    			memcpy(ch[nq],ch[q],sizeof(ch[q]));
    			fa[nq]=fa[q];//!!!
    			fa[np]=fa[q]=nq;
    			for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
    		}
    	}
    }
    
    inline void work(){
    	scanf("%s",s+1); n=strlen(s+1);	S=last=++cnt;
    	for(int i=1;i<=n;i++) a[i]=s[i]-'a';
    	for(int i=1;i<=n;i++) add(i);
    
    	scanf("%s",s+1); ans=0; L=0;
    	m=strlen(s+1); int now,p=S;
    	for(int i=1;i<=m;i++) {
    		now=s[i]-'a';
    		while(p>S && !ch[p][now]) p=fa[p],L=len[p];
    		if(ch[p][now]) {
    			L++;
    			p=ch[p][now];
    		}
    		ans=max(ans,L);
    	}
    	ans=max(ans,L);
    	printf("%d",ans);
    }
    
    int main()
    {
        work();
        return 0;
    }
    //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
    

      

  • 相关阅读:
    if判断语句和循环语句
    列表,元祖,字典的详细概述
    day10
    day09
    day08
    java---基本程序设计总结
    day07
    day06
    day05
    day04
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6582857.html
Copyright © 2011-2022 走看看