• SP1812 LCS2


    还是求几个串的最长公共串。

    但是由于数据范围的原因,用后缀数组可能会T,所以现在介绍一种后缀自动机的解法。

    首先考虑两个串的公共串怎么求(假设分别为 (S)(T))。对 (S) 建立后缀自动机,把 (T) 放在后缀自动机上跑,如果没有转移就跳后缀 (link)。然后在每个节点记录一个最大值最后取个 (max) 就行。

    现在你有很多串。对第一个串建SAM,然后其余每个串在SAM上跑一遍,还是每个节点存一下公共串的最大值,注意 (parent) 树上的每个子孙对祖先都有贡献,然后就做完了。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    
    using namespace std;
    
    const int INF=1<<30,N=3000000;
    char s[N];
    int ans[N];
    struct Suffix_DFA
    {
    	int head[N],cnt,Siz,last,Max[N];
    	struct SAM
    	{
    		int link,ch[30],len;
    	}sam[N];
    	struct Edge
    	{
    		int nxt,to;
    	}g[N*2];
    	
    	void add(int from,int to)
    	{
    		g[++cnt].nxt=head[from];
    		g[cnt].to=to;
    		head[from]=cnt;
    	}
    	
    	void SAM_Extend(int k)
    	{
    		int cur=++Siz;
    		sam[cur].len=sam[last].len+1;
    		int p=last;
    		while(p!=-1&&!sam[p].ch[k])
    			sam[p].ch[k]=cur,
    			p=sam[p].link;
    		if(p==-1)
    			sam[cur].link=0;
    		else
    		{
    			int q=sam[p].ch[k];
    			if(sam[q].len==sam[p].len+1)
    				sam[cur].link=q;
    			else
    			{
    				int clone=++Siz;
    				sam[clone].len=sam[p].len+1;
    				sam[clone].link=sam[q].link;
    				for (int i=0;i<26;i++)
    					sam[clone].ch[i]=sam[q].ch[i];
    				while(p!=-1&&sam[p].ch[k]==q)
    					sam[p].ch[k]=clone,
    					p=sam[p].link;
    				sam[cur].link=sam[q].link=clone;
    			}
    		}
    		last=cur;
    	}
    	
    	void build()
    	{
    		for (int i=1;i<=Siz;i++)
    			add(sam[i].link,i);
    	}
    	
    	void DFS(int x)
    	{
    		for (int i=head[x];i;i=g[i].nxt)
    		{
    			int v=g[i].to;
    			DFS(v);
    			Max[x]=min(sam[x].len,max(Max[x],Max[v]));
    		}
    		ans[x]=min(ans[x],Max[x]);
    	}
    	
    	void work(char s[],int len)
    	{
    		memset(Max,0,sizeof(Max));
    		int l=0,k=0;
    		for (int i=1;i<=len;i++)
    		{
    			int t=s[i]-'a';
    			while(k&&!sam[k].ch[t])
    				k=sam[k].link,
    				l=sam[k].len;
    			if(sam[k].ch[t])
    				l++,k=sam[k].ch[t];
    			Max[k]=max(Max[k],l);
    		}
    		DFS(0);
    	}
    }S;
    
    void work()
    {
    	S.sam[0].link=-1;
    	scanf("%s",s+1);
    	int len=strlen(s+1);
    	for (int i=1;i<=len;i++)
    		S.SAM_Extend(s[i]-'a');
    	S.build();
    	for (int i=1;i<=S.Siz;i++)
    		ans[i]=INF;
    	while(~scanf("%s",s+1))
    	{
    		len=strlen(s+1);
    		S.work(s,len);
    	}
    	int Ans=0;
    	for (int i=1;i<=S.Siz;i++)
    		Ans=max(Ans,ans[i]);
    	printf("%d
    ",Ans);
    }
    
    int main()
    {
    	work();
    	return 0;
    }
    
    由于博主比较菜,所以有很多东西待学习,大部分文章会持续更新,另外如果有出错或者不周之处,欢迎大家在评论中指出!
  • 相关阅读:
    04_Javascript初步第二天(上)
    用python实现省市县多级嵌套下拉列表
    爬虫之 BeautifulSoup与Xpath
    爬虫之 selenium模块
    爬虫请求库 requests
    抽屉网自动点赞 评论
    爬取京东商品信息
    爬取豆瓣电影top250
    爬虫基本原理
    Django auth认证
  • 原文地址:https://www.cnblogs.com/With-penguin/p/13363890.html
Copyright © 2020-2023  润新知