• 【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;
    }
    
    
  • 相关阅读:
    python入门1
    查找字段 和查找组件
    DBGRID 拖动滚动条 和 鼠标滚轮的问题
    数据集 过滤时 RecordCount 属性
    查找字段 如何 过滤
    数据集控件 放在 数据模块 上后,如何写事件代码
    取TTable 过滤后的记录数
    判断 Windows操作系统是32位还是64位
    MatchText MatchStr 区别
    EClassNotFound
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8456934.html
Copyright © 2020-2023  润新知