zoukankan      html  css  js  c++  java
  • hdu5790

    都快忘了在这类题的经典做法了……

    将字符串一个个的插入字典树,在字典树维护好有该前缀串s的最大编号字符串j,我们记作j控制了前缀串s

    对于当前的第i个字符串,维护此时有当前每个字符串控制了多少个前缀串,用一个线段树维护。

    由于询问是在线的,所以用主席树来维护。于是对一个询问(l,r),在第r个线段树求一下区间(l,r)的和即为答案。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 
     6 using namespace std;
     7 struct node{int l,r,s;} tree[200010*20];
     8 int go[100010][26],h[100010],be[100010];
     9 char s[100010];
    10 int m,t,n,q;
    11 
    12 int build(int l,int r)
    13 {
    14   ++t; tree[t].l=tree[t].r=tree[t].s=0;
    15   if (l==r) return t;
    16   else {
    17       int cur=t,m=(l+r)>>1;
    18       tree[cur].l=build(l,m);
    19       tree[cur].r=build(m+1,r);
    20       return cur;
    21   }
    22 }
    23 
    24 int work(int l,int r,int last,int x,int w)
    25 {
    26   ++t; tree[t]=tree[last];
    27   if (l==r) {tree[t].s+=w; return t;}
    28   else {
    29       int cur=t,m=(l+r)>>1;
    30       if (x<=m) tree[cur].l=work(l,m,tree[last].l,x,w);
    31       else tree[cur].r=work(m+1,r,tree[last].r,x,w);
    32       tree[cur].s=tree[tree[cur].l].s+tree[tree[cur].r].s;
    33       return cur;
    34   }
    35 }
    36 
    37 int ask(int l,int r,int p,int x,int y)
    38 {
    39   if (x<=l&&y>=r) return tree[p].s;
    40   else {
    41       int m=(l+r)>>1,s=0;
    42       if (x<=m) s+=ask(l,m,tree[p].l,x,y);
    43       if (y>m) s+=ask(m+1,r,tree[p].r,x,y);
    44       return s;
    45   }
    46 }
    47 
    48 int main()
    49 {
    50   while (scanf("%d",&n)!=EOF)
    51   {
    52     t=m=0;
    53     h[0]=build(1,n);
    54     memset(go[0],0,sizeof(go[0]));
    55     for (int i=1; i<=n; i++)
    56     {
    57       scanf("%s",s+1);
    58       int k=0,l=strlen(s+1);
    59       h[i]=h[i-1];
    60       for (int j=1; j<=l; j++)
    61       {
    62         int c=s[j]-'a';
    63         if (!go[k][c]) {go[k][c]=++m; memset(go[m],0,sizeof(go[m])); be[m]=0;}
    64         k=go[k][c];
    65         if (be[k]) h[i]=work(1,n,h[i],be[k],-1);
    66         be[k]=i;
    67       }
    68       h[i]=work(1,n,h[i],i,l);
    69     }
    70     scanf("%d",&q);
    71     int z=0;
    72     for (int i=1; i<=q; i++)
    73     {
    74       int l,r;
    75       scanf("%d%d",&l,&r);
    76       l=(z+l)%n+1; r=(z+r)%n+1;
    77       if (l>r) swap(l,r);
    78       z=ask(1,n,h[r],l,r);
    79       printf("%d
    ",z);
    80     }
    81   }
    82   return 0;
    83 }
    View Code
  • 相关阅读:
    Linux workqueue疑问【转】
    Java中基础类库使用
    Sdut 2164 Binomial Coeffcients (组合数学) (山东省ACM第二届省赛 D 题)
    python中使用mahotas包实现高斯模糊
    ZOJ1372 POJ 1287 Networking 网络设计 Kruskal算法
    Android 属性动画(Property Animation) 全然解析 (下)
    MySQL搜索: WHERE 多条件
    点滴记录——Centos 6.5 yum安装Ganglia
    标准linuxserver搭建
    检查ORACLE的警告文件的脚本
  • 原文地址:https://www.cnblogs.com/phile/p/5806773.html
Copyright © 2011-2022 走看看