zoukankan      html  css  js  c++  java
  • 【BZOJ3277】串(后缀自动机)

    【BZOJ3277】串(后缀自动机)

    题面

    BZOJ

    题解

    广义后缀自动机???
    照着别人的打了一遍。。
    相当于每个串都构建一个后缀自动机
    构建完一个串之后,直接把当前的last指回root就行了???
    好吧,我觉得我看了一个假的广义后缀自动机。。

    不过这道题这样就行了
    考虑如何计算一个串在多少个母串中出现过?
    考虑他的(right)集合中有多少个母串的结束位置就好了
    那么,每个节点开个(set)存一下,然后按照拓扑序向上合并一次
    因为(parent)包含的母串个数一定较大,
    所以,对于每一个串计算答案
    就把他直接丢到广义后缀自动机里面去
    如果当前位置的(size),也就是包含的母串个数(<K)
    就跳父亲
    那么,当前位置产生的贡献就是(longest)
    累加就好了

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define RG register
    #define MAX 220000
    struct Line{int v,next;}e[MAX<<1];
    int h[MAX<<1],cnt=1;
    inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
    struct Node
    {
    	int son[26];
    	int ff,len;
    	set<int> d;
    }t[MAX<<1];
    int size[MAX<<1];
    int last,tot;
    void init(){last=tot=1;}
    void extend(int c,int id)
    {
    	int p=last,np=++tot;last=np;
    	t[np].len=t[p].len+1;
    	t[np].d.insert(id);
    	while(p&&!t[p].son[c])t[p].son[c]=np,p=t[p].ff;
    	if(!p)t[np].ff=1;
    	else
    	{
    		int q=t[p].son[c];
    		if(t[q].len==t[p].len+1)t[np].ff=q;
    		else
    		{
    			int nq=++tot;
    			t[nq]=t[q];
    			t[nq].len=t[p].len+1;
    			t[q].ff=t[np].ff=nq;
    			while(p&&t[p].son[c]==q)t[p].son[c]=nq,p=t[p].ff;
    		}
    	}
    }
    void DFS(int u)
    {
    	for(int i=h[u];i;i=e[i].next)
    	{
    		int v=e[i].v;
    		DFS(v);
    		for(set<int>::iterator it=t[v].d.begin();it!=t[v].d.end();++it)
    			t[u].d.insert(*it);
    	}
    	size[u]=t[u].d.size();
    }	
    int n,K;
    string g[MAX];
    int main()
    {
    	ios::sync_with_stdio(false);
    	init();
    	cin>>n>>K;
    	for(int i=1;i<=n;++i)
    	{
    		cin>>g[i];
    		last=1;
    		for(int j=0,l=g[i].length();j<l;++j)extend(g[i][j]-97,i);
    	}
    	for(int i=1;i<=tot;++i)if(t[i].ff)Add(t[i].ff,i);
    	DFS(1);
    	if(K>n){for(int i=1;i<=n;++i)putchar('0'),putchar(' ');return 0;}
    	for(int i=1;i<=n;++i)
    	{
    		ll ans=0;
    		int now=1,len=g[i].length();
    		for(int j=0;j<len;++j)
    		{
    			now=t[now].son[g[i][j]-97];
    			while(size[now]<K)now=t[now].ff;
    			ans+=t[now].len;
    		}
    		printf("%lld ",ans);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    Windows NT 技术简介
    IOS7上呈现IOS6的水滴刷新效果
    Asp.net HttpWebRequest和HttpWebResponse发送和接受任何类型数据
    QQ互联OAuth2.0 .NET SDK 发布以及网站QQ登陆示例代码
    在PowerDesigner中设计物理模型1——表和主外键
    mantisbt邮件配置
    Mantis安装与配置
    Mime类型与文件后缀对照表及探测文件MIME的方法
    MIME类型-服务端验证上传文件的类型
    SWFUpload 2.5.0版 官方说明文档 中文翻译版
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8456934.html
Copyright © 2011-2022 走看看