• spoj LCS2


    多串LCS很适合SA但是我要学SAM
    对第一个串求SAM,然后把剩下的串在SAM上跑,也就是维护p和len,到一个点,如果有ch[p][c],就p=ch[p][c],len++,否则向fa找最下的有c[p][c]的p,然后len=dis[p]+1,p=ch[p][c],否则就p=root,len=0(这个len每到一个节点就更新这个节点的f)
    然后注意到在parent树上,因为每个节点代表的right集合是儿子的并集,所以f[u]是可以更新f[fa[u]]的,所以从底向上更新一遍(注意先更新!!)
    最终点u的f就是每个串的f与dis[u]取min,然后ans在这些点上取max



    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=500005;
    int n,m=1,fa[N],ch[N][27],dis[N],cur=1,con=1,la,f[N][15],c[N],a[N],ans;
    char s[N];
    void ins(int c,int id)
    {
        la=cur,dis[cur=++con]=id;
        int p=la;
        for(;p&&!ch[p][c];p=fa[p])
            ch[p][c]=cur;
        if(!p)
            fa[cur]=1;
        else
        {
            int q=ch[p][c];
            if(dis[q]==dis[p]+1)
                fa[cur]=q;
            else
            {
                int nq=++con;
                dis[nq]=dis[p]+1;
                memcpy(ch[nq],ch[q],sizeof(ch[q]));
                fa[nq]=fa[q];
                fa[q]=fa[cur]=nq;
                for(;ch[p][c]==q;p=fa[p])
                    ch[p][c]=nq;
            }
        }
    }
    int main()
    {
    	scanf("%s",s+1);
    	n=strlen(s+1);
    	for(int i=1;i<=n;i++)
    		ins(s[i]-'a',i);
    	for(int i=1;i<=con;i++)
    		f[i][1]=dis[i];
    	while(~scanf("%s",s+1))
    	{
    		n=strlen(s+1),m++;
    		for(int i=1,p=1,len=0;i<=n;i++)
    		{
    			int c=s[i]-'a';
    			if(ch[p][c])
    				len++,p=ch[p][c],f[p][m]=max(f[p][m],len);
    			else
    			{
    				for(;p&&!ch[p][c];p=fa[p]);
    				if(!p)
    					p=1,len=0;
    				else
    					len=dis[p]+1,p=ch[p][c],f[p][m]=max(f[p][m],len);
    			}
    		}
    	}
    	for(int i=1;i<=con;i++)
    		c[dis[i]]++;
    	for(int i=1;i<=con;i++)
    		c[i]+=c[i-1];
    	for(int i=1;i<=con;i++)
    		a[c[dis[i]]--]=i;
    	for(int j=2;j<=m;j++)
    		for(int i=con;i>=1;i--)
    			f[fa[a[i]]][j]=max(f[fa[a[i]]][j],f[a[i]][j]);
    	for(int i=1;i<=con;i++)
    	{
    		for(int j=2;j<=m;j++)
    			f[i][1]=min(f[i][1],f[i][j]);
    		ans=max(ans,f[i][1]);
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    bzoj3524: [Poi2014]Couriers(主席树)
    51nod 1275 连续子段的差异(twopointer+单调队列)
    51nod 1274 最长递增路径(DP)
    51nod 1273 旅行计划(思维题)
    51nod 1257 背包问题 V3(分数规划)
    CSS 几款比较常用的翻转特效
    css文字飞入效果
    jQuery使用方法
    数据库
    关系型数据库基本概念及MySQL简述
  • 原文地址:https://www.cnblogs.com/lokiii/p/10005663.html
Copyright © 2020-2023  润新知