• hdu_5790_Prefix(trie+主席树)


    题目链接:hdu_5790_Prefix

    题意:

    给你n个字符串,字符串总长度不超过10W,然后给你一个区间,问你这个区间的字符串不相同的前缀有多少个。

    题解:

    由于z与上一个答案有关,所以强制在线,区间询问可以用主席树搞搞。

    不同前缀的话,我们可以用一个trie来记录每一个节点的最晚出现时间,也就代表了这个前缀最晚出现的时间,然后保存到对应的主席树中。

    这样就转换为询问区间不大于l的数有多少个。

     1 #include<bits/stdc++.h>
     2 #define F(i,a,b) for(int i=a;i<=b;i++)
     3 using namespace std;
     4 
     5 const int N=1e5+7;
     6 char s[N];
     7 int root[N],tot,n,q;
     8 struct node{int l,r,sum;}T[25*N];
     9 
    10 void update(int &x,int y,int pos,int l=1,int r=n)
    11 {
    12     T[++tot]=T[y],T[tot].sum++,x=tot;
    13     if(l==r)return;
    14     int m=l+r>>1;
    15     if(pos<=m)update(T[x].l,T[y].l,pos,l,m);
    16     else update(T[x].r,T[y].r,pos,m+1,r);
    17 }
    18 
    19 int query(int x,int y,int k,int l=1,int r=n)
    20 {
    21     if(l==r)return T[x].sum-T[y].sum;
    22     int m=l+r>>1;
    23     if(k<=m)return query(T[x].l,T[y].l,k,l,m);
    24     else return T[T[x].l].sum-T[T[y].l].sum+query(T[x].r,T[y].r,k,m+1,r);
    25 }
    26 
    27 struct Trie{
    28     int tr[N][26],tot,mx[N];
    29     void nd(){mx[++tot]=0,memset(tr[tot],0,sizeof(tr[tot]));}
    30     void init(){tot=-1,nd();}
    31     void insert(char *s,int time)
    32     {
    33         int t1=root[time-1],t2;
    34         for(int i=0,x=0;s[i]!='';i++)
    35         {
    36             if(!tr[x][s[i]-'a'])
    37             {
    38                 nd(),update(t2,t1,1);
    39                 t1=t2,tr[x][s[i]-'a']=tot,mx[tot]=time,x=tot;
    40             }
    41             else update(t2,t1,mx[x=tr[x][s[i]-'a']]+1),t1=t2,mx[x]=time;
    42         }
    43         root[time]=t1;
    44     }
    45 }trie;
    46 
    47 void init(){tot=0;trie.init();}
    48 
    49 int main()
    50 {
    51     while(~scanf("%d",&n))
    52     {
    53         init();
    54         F(i,1,n)scanf("%s",s),trie.insert(s,i);
    55         scanf("%d",&q);
    56         int l,r,z=0;
    57         F(i,1,q)
    58         {
    59             scanf("%d%d",&l,&r);
    60             l=(z+l)%n+1,r=(z+r)%n+1;
    61             if(l>r)l^=r,r^=l,l^=r;
    62             printf("%d
    ",z=query(root[r],root[l-1],l));
    63         }
    64     }
    65     return 0;
    66 }
    View Code
  • 相关阅读:
    Django框架基础之分页
    Django框架基础之session
    Django框架基础之COOKIE
    Django框架基础(二)
    linux挂载/卸载windows共享文件夹
    std::string 字符串操作(分割,去空格)
    Ubuntu sudo不用输入密码的方法
    Qt学习
    ubuntu上利用 checkinstall/dpkg 制作/安装/卸载deb或rpm包
    wxWidgets编译安装
  • 原文地址:https://www.cnblogs.com/bin-gege/p/5957616.html
Copyright © 2020-2023  润新知