zoukankan      html  css  js  c++  java
  • loj6198 谢特

    题目

    显然可以构造一棵后缀树,将问题转化成了在这棵树上找到两个点(i,j),使得(w_iigoplus w_j+ len_{ m LCA(i,j)})最大

    于是在树上(dfs)的时候启发式合并( m trie)就好了,发现自己已经菜到不会写( m trie)了,( m trie)的插入做到最后一层还是有节点的,得先添加这个节点,之后才能返回

    #include<bits/stdc++.h>
    #define re register
    #define LL long long
    const int maxn=2e5+5;
    inline int read() {
    	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    std::vector<int> v[maxn];
    char S[maxn>>1];
    int a[maxn>>1],tax[maxn>>1],A[maxn];
    int ch[maxn*25][2];
    int len[maxn],son[maxn][26],rt[maxn],fa[maxn];
    int n,lst=1,cnt=1,tot,ans;
    inline int max(int a,int b) {return a>b?a:b;}
    inline int ins(int now,int w,int v) {
    	if(!now) now=++tot;
    	if(w==-1) return now;
    	int u=(v>>w)&1;
    	ch[now][u]=ins(ch[now][u],w-1,v);
    	return now;
    }
    inline int chk(int now,int w,int v) {
    	if(w==-1) return 0;
    	int u=(v>>w)&1;
    	if(ch[now][u^1]) return (1<<w)+chk(ch[now][u^1],w-1,v);
    	return chk(ch[now][u],w-1,v);
    }
    inline int merge(int a,int b) {
    	if(!a||!b) return a+b;
    	ch[a][0]=merge(ch[a][0],ch[b][0]);
    	ch[a][1]=merge(ch[a][1],ch[b][1]);
    	return a;
    }
    inline void extend(int c,int w) {
    	int p=++cnt,f=lst;lst=cnt;
    	len[p]=len[f]+1,rt[p]=ins(rt[p],16,w);v[p].push_back(w);
    	while(f&&!son[f][c]) son[f][c]=p,f=fa[f];
    	if(!f) {fa[p]=1;return;}
    	int x=son[f][c];
    	if(len[f]+1==len[x]) {fa[p]=x;return;}
    	int y=++cnt;
    	len[y]=len[f]+1,fa[y]=fa[x],fa[x]=fa[p]=y;
    	for(re int i=0;i<26;i++) son[y][i]=son[x][i];
    	while(f&&son[f][c]==x) son[f][c]=y,f=fa[f];
    }
    int main() {
    	n=read();scanf("%s",S+1);for(re int i=1;i<=n;i++) a[i]=read();
    	for(re int i=n;i;--i) extend(S[i]-'a',a[i]);
    	for(re int i=1;i<=cnt;i++) tax[len[i]]++;
    	for(re int i=1;i<=n;i++) tax[i]+=tax[i-1];
    	for(re int i=1;i<=cnt;i++) A[tax[len[i]]--]=i;
    	for(re int i=cnt;i;--i) {
    		int x=A[i];
    		if(v[x].size()>v[fa[x]].size()) 
    			std::swap(rt[x],rt[fa[x]]),std::swap(v[x],v[fa[x]]);
    		int now=0;
    		for(re int j=0;j<v[x].size();j++) {
    			v[fa[x]].push_back(v[x][j]);
    			now=max(now,chk(rt[fa[x]],16,v[x][j]));
    		}
    		rt[fa[x]]=merge(rt[fa[x]],rt[x]);
    		ans=max(ans,now+len[fa[x]]);
    	}
    	std::cout<<ans;return 0;
    }
    
  • 相关阅读:
    使用WCF实现SOA面向服务编程—— 架构设计
    ASP.NET MVC 4 RC的JS/CSS打包压缩功能
    自定义WCF的配置文件
    C#综合揭秘——分部类和分部方法
    结合领域驱动设计的SOA分布式软件架构
    【转】数字证书类型
    kubeadm部署单master Kuberntes集群
    持续交付
    编译在docker alpine中可用的go程序
    百度云盘,文件重命名
  • 原文地址:https://www.cnblogs.com/asuldb/p/11414328.html
Copyright © 2011-2022 走看看