zoukankan      html  css  js  c++  java
  • 【BZOJ3879】—SvT(后缀自动机+虚树/后缀自动机+单调栈)

    传送门

    后缀数组终于跑过了SamSam

    后缀自动机上虚树是显然的
    后缀数组就按rkrk排序后考虑每个位置的贡献,显然就是左右都比他大的时候
    单调栈维护一下就是了


    后缀数组+单调栈

    #include<bits/stdc++.h>
    using namespace std;
    const int RLEN=1<<20|1;
    inline char gc(){
        static char ibuf[RLEN],*ib,*ob;
        (ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
        return (ib==ob)?EOF:*ib++;
    }
    inline int read(){
        char ch=gc();
        int res=0,f=1;
        while(!isdigit(ch))f^=ch=='-',ch=gc();
        while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
        return f?res:-res;
    }
    inline void readstring(char *s){
    	int len=0;char c;
    	while(isspace(c=gc()));
    	while(s[len++]=c,!isspace(c=gc())&&c!=EOF);
    }
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define re register
    #define pb push_back
    #define ll long long
    inline void file(){
        #ifdef Stargazer
        freopen("lx.cpp","r",stdin);
        #endif
    }
    const int N=1000005;
    namespace Sa{
    	int rk[N],sa[N],sa2[N],cnt[N],n,m,s[N],ht[N];
    	inline void Sort(){
    		for(int i=1;i<=m;i++)cnt[i]=0;
    		for(int i=1;i<=n;i++)cnt[rk[sa2[i]]]++;
    		for(int i=1;i<=m;i++)cnt[i]+=cnt[i-1];
    		for(int i=n;i>=1;i--)sa[cnt[rk[sa2[i]]]--]=sa2[i];
    	}
    	inline void build(){
    		m=30;
    		for(int i=1;i<=n;i++)rk[i]=s[i],sa2[i]=i;
    		Sort();
    		for(int i=1,pos=0;i<=n&&pos<n;i<<=1){
    			pos=0;
    			for(int j=n-i+1;j<=n;j++)sa2[++pos]=j;
    			for(int j=1;j<=n;j++)if(sa[j]>i)sa2[++pos]=sa[j]-i;
    			Sort();
    			pos=1,swap(sa2,rk);
    			rk[sa[1]]=1;
    			for(int j=2;j<=n;j++)
    				rk[sa[j]]=(sa2[sa[j]]==sa2[sa[j-1]])&&(sa2[sa[j]+i]==sa2[sa[j-1]+i])?pos:++pos;
    			m=pos;
    		}
    		for(int i=1,j,k=0;i<=n;ht[rk[i++]]=k)
    		for(k?k--:0,j=sa[rk[i]-1];s[i+k]==s[j+k];k++);
    	}
    	int st[21][N],lg[N];
    	inline void buildst(){
    		lg[0]=-1;
    		for(int i=1;i<=n;i++)lg[i]=lg[i>>1]+1,st[0][i]=ht[i];
    		for(int i=1;(1<<i)<=n;i++)
    		for(int j=1;j+(1<<i)-1<=n;j++)
    		st[i][j]=min(st[i-1][j],st[i-1][j+(1<<(i-1))]);
    	}
    	inline int lcp(int x,int y){
    		x=rk[x],y=rk[y];
    		if(x>y)swap(x,y);x++;
    		int t=lg[y-x+1];
    		return min(st[t][x],st[t][y-(1<<t)+1]);
    	}
    }
    inline bool comp(int a,int b){
    	return Sa::rk[a]<Sa::rk[b];
    }
    inline void calc(){
    	static int a[N],val[N],stk[N],l[N],r[N],top;
    	int n=read(),res=0;
    	for(int i=1;i<=n;i++)a[i]=read();
    	sort(a+1,a+n+1,comp),n=unique(a+1,a+n+1)-a-1;
    	for(int i=1;i<n;i++)val[i]=Sa::lcp(a[i],a[i+1]);
    	for(int i=1;i<n;i++){
    		while(top&&val[stk[top]]>=val[i])r[stk[top--]]=i;
    		stk[++top]=i;
    	}
    	while(top)r[stk[top--]]=n;
    	for(int i=n-1;i;i--){
    		while(top&&val[stk[top]]>val[i])l[stk[top--]]=i;
    		stk[++top]=i;
    	}
    	while(top)l[stk[top--]]=0;
    	for(int i=1;i<n;i++)
    	res+=1ll*val[i]*(i-l[i])*(r[i]-i);
    	cout<<res<<'
    ';
    }
    int n,m;
    char s[N];
    int main(){
    	file();
    	n=read(),m=read();
    	readstring(s+1);
    	Sa::n=strlen(s+1);
    	for(int i=1;i<=Sa::n;i++)Sa::s[i]=s[i]-'a'+1;
    	Sa::build(),Sa::buildst();
    	for(int i=1;i<=m;i++)
    	calc();
    }
    

    后缀自动机+虚树

    #include<bits/stdc++.h>
    using namespace std;
    const int RLEN=1<<20|1;
    inline char gc(){
        static char ibuf[RLEN],*ib,*ob;
        (ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
        return (ib==ob)?EOF:*ib++;
    }
    inline int read(){
        char ch=gc();
        int res=0,f=1;
        while(!isdigit(ch))f^=ch=='-',ch=gc();
        while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
        return f?res:-res;
    }
    inline void readstring(char *s){
    	int len=0;char c;
    	while(isspace(c=gc()));
    	while(s[len++]=c,!isspace(c=gc())&&c!=EOF);
    }
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define re register
    #define pb push_back
    #define ll long long
    inline void file(){
        #ifdef Stargazer
        freopen("lx.cpp","r",stdin);
        #endif
    }
    const int N=1000005;
    namespace Sam{
    	int nxt[N][26],fa[N],len[N],tot,last;
    	inline void insert(int c){
    		int cur=++tot,p=last;last=cur;
    		len[cur]=len[p]+1;
    		for(;p&&!nxt[p][c];p=fa[p])nxt[p][c]=cur;
    		if(!p)fa[cur]=1;
    		else {
    			int q=nxt[p][c];
    			if(len[p]+1==len[q])fa[cur]=q;
    			else{
    				int clo=++tot;
    				memcpy(nxt[clo],nxt[q],sizeof(nxt[q]));
    				fa[clo]=fa[q],len[clo]=len[p]+1;
    				fa[q]=fa[cur]=clo;
    				for(;p&&nxt[p][c]==q;p=fa[p])nxt[p][c]=clo;
    			}
    		}
    	}
    }
    namespace G{
    	vector<int> e[N];
    	int tot,in[N],out[N],dep[N],top[N],fa[N],siz[N],son[N],pos[N];
    	int a[N],vis[N],ok[N],stk[N],tp,T;
    	ll ans;
    	inline void addedge(int u,int v){
    		e[u].pb(v);
    	}
    	inline bool comp(int a,int b){
    		return in[a]<in[b];
    	}
    	void dfs1(int u){
    		siz[u]=1;
    		for(int &v:e[u]){
    			if(v==fa[u])continue;
    			fa[v]=u,dep[v]=dep[u]+1;
    			dfs1(v),siz[u]+=siz[v];
    			if(siz[v]>siz[son[u]])son[u]=v;
    			siz[v]=0;
    		}
    	}
    	void dfs2(int u,int tp){
    		in[u]=++tot,top[u]=tp;
    		if(son[u])dfs2(son[u],tp);
    		for(int &v:e[u]){
    			if(v==son[u]||v==fa[u])continue;
    			dfs2(v,v);
    		}
    		out[u]=tot;
    		e[u].clear();
    	}
    	inline int Lca(int u,int v){
    		while(top[u]!=top[v]){
    			if(dep[top[u]]<dep[top[v]])swap(u,v);
    			u=fa[top[u]];
    		}
    		return dep[u]<dep[v]?u:v;
    	}
    	void calc(int u){
    		siz[u]=ok[u],ok[u]=0;
    		for(int &v:e[u]){
    			calc(v);
    			ans+=1ll*siz[u]*siz[v]*Sam::len[u];
    			siz[u]+=siz[v];
    		}
    		e[u].clear();
    	}
    	inline void solve(){
    		int m=read(),n=0;T++;ans=0;
    		memset(siz,0,sizeof(siz));
    		for(int i=1;i<=m;i++){
    			int p=read();
    			if(vis[p]==T)continue;
    			vis[p]=T,a[++n]=pos[p],ok[pos[p]]=1;
    		}
    		sort(a+1,a+n+1,comp);
    		stk[tp=1]=1;
    		for(int i=1;i<=n;i++){
    			int lca=Lca(stk[tp],a[i]);
    			while(in[lca]<in[stk[tp]]){
    				if(in[lca]>=in[stk[tp-1]]){
    					addedge(lca,stk[tp--]);
    					if(stk[tp]!=lca)stk[++tp]=lca;
    					break;
    				}
    				addedge(stk[tp-1],stk[tp]),tp--;
    			}
    			stk[++tp]=a[i];
    		}
    		while(tp>1)addedge(stk[tp-1],stk[tp]),tp--;
    		calc(1);cout<<ans<<'
    ';
    	}
    }
    int n,m;
    char s[N];
    int main(){
    	file();
    	n=read(),m=read();
    	readstring(s+1);
    	Sam::last=Sam::tot=1;
    	for(int i=strlen(s+1);i;i--)Sam::insert(s[i]-'a'),G::pos[i]=Sam::last;
    	for(int i=2;i<=Sam::tot;i++)G::addedge(Sam::fa[i],i);
    	G::dfs1(1),G::dfs2(1,1);
    	for(int i=1;i<=m;i++)
    		G::solve();
    }
    
  • 相关阅读:
    node.js 安装后怎么打开 node.js 命令框
    thinkPHP5 where多条件查询
    网站title中的图标
    第一次写博客
    Solution to copy paste not working in Remote Desktop
    The operation could not be completed. (Microsoft.Dynamics.BusinessConnectorNet)
    The package failed to load due to error 0xC0011008
    VS2013常用快捷键
    微软Dynamics AX的三层架构
    怎样在TFS(Team Foundation Server)中链接团队项目
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328786.html
Copyright © 2011-2022 走看看