loj6198 谢特

Posted asuldb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了loj6198 谢特相关的知识,希望对你有一定的参考价值。

题目

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

于是在树上\(dfs\)的时候启发式合并\(\rm trie\)就好了,发现自己已经菜到不会写\(\rm trie\)了,\(\rm 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;

以上是关于loj6198 谢特的主要内容,如果未能解决你的问题,请参考以下文章

谢特——后缀数组+tire 树

HDU6198

hdu 6198(矩阵快速幂)

HDU 6198 2017沈阳网络赛 线形递推

HDU 6198 number number number 矩阵快速幂 找规律

HDU6198 number number number(杜教BM模板)