zoukankan      html  css  js  c++  java
  • BZOJ 5084: hashit 后缀自动机(原理题)

    比较考验对后缀自动机构建过程的理解. 

    之前看题解写的都是树链的并,但是想了想好像可以直接撤销,复杂度是线性的. 

    自己想出来的,感觉后缀自动机的题应该不太能难倒我~ 

    注意:一定要手画一下后缀自动机的构建过程,然后看着自己画的图一步一步模拟即可. 

    Code: 

    #include <stack> 
    #include <cstdio> 
    #include <cstring> 
    #include <algorithm>  
    #define N 200003 
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin) // ,freopen(s".out","w",stdout)    
    using namespace std;   
    struct Node 
    { 
    	int node,i,p,fanq,q; 
    	Node(int node=0,int i=0,int p=0,int fanq=0,int q=0):node(node),i(i),p(p),fanq(fanq),q(q){}   
    }; 
    ll now; 
    char S[N];     
    stack<Node>sta;    
    int ch[N][26],f[N],len[N],pre[N],tot,n,C[N];   
    int extend(int lst,int c) 
    {  
    	int np=++tot,p=lst; 
    	len[np]=len[p]+1;                    
    	for(;p&&!ch[p][c];p=f[p]) ch[p][c]=np;       
    	if(!p) f[np]=1; 
        else 
        {
        	int q=ch[p][c]; 
        	if(len[q]==len[p]+1) f[np]=q; 
        	else 
        	{
        		int nq=++tot; 
        		len[nq]=len[p]+1, f[nq]=f[q], f[np]=f[q]=nq;                 
        		sta.push(Node(nq,np,p,f[nq],q));       
        		memcpy(ch[nq],ch[q],sizeof(ch[q]));    
        		for(;p&&ch[p][c]==q;p=f[p]) ch[p][c]=nq;       
        	}
        }  
        now+=(ll)len[np]-len[f[np]];                    
        sta.push(Node(np,np,lst,0,0)); 
        return np;     
    }   
    int main() 
    {
    	int i,j,cur;             
    	scanf("%s",S+1),n=strlen(S+1);   
    	cur=pre[1]=tot=1;     
    	for(i=1;i<=n;++i) 
    	{
    		if(S[i]=='-') 
    		{ 
    			while(!sta.empty() && sta.top().i==cur) 
    			{
    			    Node e=sta.top(); sta.pop(); 
    			    if(e.fanq) 
    			    {  
    			    	int p=e.p,fanq=e.fanq,nq=e.node,q=e.q,c=C[e.i];         
    			    	for(;p&&ch[p][c]==nq;p=f[p]) ch[p][c]=q;        
    			    	f[q]=f[nq];            
    			    }	
    			    else 
    			    { 
    			    	int np=e.node,p=e.p,c=C[e.i];         
    			    	now-=(len[np]-len[f[np]]);          
    			    	for(;p&&ch[p][c]==np;p=f[p]) ch[p][c]=0;                  
    			    }
    			}
    			cur=pre[cur];   
    		}
    		else 
    		{   
    			int x=cur;   
    			cur=extend(x,S[i]-'a'), pre[cur]=x, C[cur]=S[i]-'a';    
    		}
    		printf("%lld
    ",now);   
    	}
    	return 0; 
    }
    

      

  • 相关阅读:
    MySQL企业常用集群图解
    MySQL常见错误类型
    MySQL 数据库增量数据恢复案例
    异地备份同步校验脚本
    python 自动化之路 day 面向对象基础
    Docker 入门
    awk知识点总结
    Linux文件管理类命令及命令别名
    Linux重定向
    Linux进程管理
  • 原文地址:https://www.cnblogs.com/guangheli/p/11436947.html
Copyright © 2011-2022 走看看