zoukankan      html  css  js  c++  java
  • *一道题20

    $n leq 200000$的字符串,$m leq 200000$次操作:1,末尾加一个字符;2,末尾删一个字符;3,一个区间中,问某个串(新给的)出现次数。强制在线。

    并不会。

    首先可以通过$nm$的复杂度成功拿到20分。

    其次可以写一个不带加字符的:建个后缀树,然后查询就是查:后缀树的一个子树里,有多少编号在一定区间(注意不是询问的区间,右端点需要调整)的后缀。不修改的在线二维数点可以用主席树。也只有20分。

      1 //#include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 //#include<time.h>
      5 //#include<complex>
      6 //#include<set>
      7 //#include<queue>
      8 //#include<vector>
      9 #include<algorithm>
     10 #include<stdlib.h>
     11 using namespace std;
     12 
     13 #define LL long long
     14 int qread()
     15 {
     16     char c; int s=0,f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1);
     17     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f;
     18 }
     19 
     20 //Pay attention to '-' , LL and double of qread!!!!
     21 
     22 int n,lq;
     23 #define maxn 400011
     24 char s[maxn],p[maxn];
     25 
     26 int getnum(char c) {if (c>='a' && c<='z') return c-'a'; return c-'A'+26;}
     27 int getch(int x) {if (x<26) return 'a'+x; return 'A'+x-26;}
     28 
     29 int fail[maxn];
     30 void solve1()
     31 {
     32     int op,x,y,last=0; char c;
     33     while (lq--)
     34     {
     35         op=qread();
     36         if (op==1)
     37         {
     38             while (((c=getchar())<'a' || c>'z') && (c<'A' || c>'Z'));
     39             c=getch((getnum(c)+last)%52);
     40             s[++n]=c;
     41         }
     42         else if (op==2) n--;
     43         else
     44         {
     45             x=qread()^last; y=qread()^last;
     46             fail[1]=fail[2]=1;
     47             int now=1;
     48             while (((c=getchar())<'a' || c>'z') && (c<'A' || c>'Z'));
     49             p[now]=getch((getnum(c)+last)%52);
     50             while (((c=getchar())>='a' && c<='z') || (c>='A' && c<='Z'))
     51             {
     52                 p[++now]=getch((getnum(c)+last)%52);
     53                 int j=fail[now];
     54                 while (j>1 && p[j]!=p[now]) j=fail[j];
     55                 fail[now+1]=p[j]==p[now]?j+1:1;
     56             }
     57             int ans=0;
     58             for (int i=x,j=1;i<=y;i++)
     59             {
     60                 while (j>1 && p[j]!=s[i]) j=fail[j];
     61                 if (p[j]==s[i]) j++;
     62                 if (j>now) {ans++; j=fail[j];}
     63             }
     64             printf("%d
    ",ans);
     65             last=ans;
     66         }
     67     }
     68 }
     69 
     70 struct Edge{int to,next;};
     71 struct SAM
     72 {
     73     struct Node{int ch[52],pos,Max,pre;}a[maxn];
     74     int size,last;
     75     int val[maxn],vvv[maxn];
     76     SAM() {a[0].pre=-1; a[0].pos=a[0].Max=size=0; last=Time=0; le=2;}
     77     void insert(int id,int pos)
     78     {
     79         int x=++size,y=last;
     80         a[x].pos=pos; a[x].Max=n-pos+1; last=x; val[x]=pos;
     81         for (;~y && !a[y].ch[id];y=a[y].pre) a[y].ch[id]=x;
     82         if (!~y) a[x].pre=0;
     83         else if (a[a[y].ch[id]].Max==a[y].Max+1) a[x].pre=a[y].ch[id];
     84         else
     85         {
     86             int w=++size,z=a[y].ch[id]; a[w]=a[z]; a[w].Max=a[y].Max+1; a[w].pos=pos;
     87             a[z].pre=a[x].pre=w;
     88             for (;~y && a[y].ch[id]==z;y=a[y].pre) a[y].ch[id]=w;
     89         }
     90     }
     91     Edge edge[maxn]; int first[maxn],le;
     92     void in(int x,int y) {Edge &e=edge[le]; e.to=y; e.next=first[x]; first[x]=le++;}
     93     int ll[maxn],rr[maxn],Time;
     94     void predfs(int x)
     95     {
     96         ll[x]=++Time; vvv[Time]=val[x];
     97         for (int i=first[x];i;i=edge[i].next)
     98         {
     99             Edge &e=edge[i];
    100             predfs(e.to);
    101         }
    102         rr[x]=Time;
    103     }
    104     void maketree()
    105     {
    106         for (int i=1;i<=size;i++) in(a[i].pre,i);
    107         Time=0; predfs(0);
    108     }
    109     bool go(int &x,int &p,char c)
    110     {
    111         Node &b=a[x];
    112         if (p) {if (s[p]==c) p++; else return 0; if (p==b.pos+b.Max) p=0;}
    113         else
    114         {
    115             bool flag=1;
    116             for (int i=first[x];i;i=edge[i].next)
    117             {
    118                 Edge &e=edge[i];
    119                 if (s[a[e.to].pos+a[x].Max]==c)
    120                 {
    121                     p=a[e.to].pos+a[x].Max+1; x=e.to;
    122                     flag=0; break;
    123                 }
    124             }
    125             if (flag) return 0;
    126             if (p==a[x].pos+a[x].Max) p=0;
    127         }
    128         return 1;
    129     }
    130 }sa;
    131 
    132 int root[maxn];
    133 struct SMT
    134 {
    135     struct Node{int ls,rs,cnt;}a[maxn*20];
    136     int size,n;
    137     void clear(int N) {n=N; size=0;}
    138     void insert(int &x,int y,int L,int R,int v)
    139     {
    140         x=++size; a[x].cnt=a[y].cnt+1;
    141         if (L==R) return;
    142         int mid=(L+R)>>1;
    143         if (v<=mid) a[x].rs=a[y].rs,insert(a[x].ls,a[y].ls,L,mid,v);
    144         else a[x].ls=a[y].ls,insert(a[x].rs,a[y].rs,mid+1,R,v);
    145     }
    146     void insert(int &x,int y,int v) {if (v) insert(x,y,1,n,v); else x=y;}
    147     int ql,qr;
    148     int Query(int y,int x,int L,int R)
    149     {
    150         if (ql<=L && R<=qr) return a[y].cnt-a[x].cnt;
    151         else
    152         {
    153             int mid=(L+R)>>1,ans=0;
    154             if (ql<=mid) ans+=Query(a[y].ls,a[x].ls,L,mid);
    155             if (qr>mid) ans+=Query(a[y].rs,a[x].rs,mid+1,R);
    156             return ans;
    157         }
    158     }
    159     int query(int y,int x,int L,int R) {ql=L; qr=R; return Query(y,x,1,n);}
    160 }t;
    161 
    162 void solve2()
    163 {
    164     for (int i=n;i;i--) sa.insert(getnum(s[i]),i);
    165     sa.maketree();
    166     t.clear(n);
    167 //    for (int i=1;i<=sa.Time;i++) cout<<sa.vvv[i]<<' ';cout<<endl;
    168     for (int i=1;i<=sa.Time;i++) t.insert(root[i],root[i-1],sa.vvv[i]);
    169     int op,x,y,last=0; char c;
    170     while (lq--)
    171     {
    172         op=qread();
    173         if (op==2) continue;
    174         x=qread()^last; y=qread()^last; y++;
    175         while (((c=getchar())<'a' || c>'z') && (c<'A' || c>'Z'));
    176         int xx=0,pp=0; bool flag=1;
    177         do
    178         {
    179             y--;
    180             c=getch((getnum(c)+last)%52);
    181             if (flag) flag=sa.go(xx,pp,c);
    182         }while (((c=getchar())>='a' && c<='z') || (c>='A' && c<='Z'));
    183         if (!flag) printf("%d
    ",(last=0));
    184         else
    185         {
    186             int R=root[sa.rr[xx]],L=root[sa.ll[xx]-1];
    187             printf("%d
    ",(last=t.query(R,L,x,y)));
    188         }
    189     }
    190 }
    191 
    192 int main()
    193 {
    194     scanf("%s",s+1); n=strlen(s+1); lq=qread();
    195     if (n<=5000 && lq<=5000) solve1();
    196     else solve2();
    197     return 0;
    198 }
    View Code

    真实做法后缀平衡树,暂时不会。

  • 相关阅读:
    Linux查看程序端口占用情况
    jQuery冒泡事件阻止
    jQuery中.bind() .live() .delegate() .on()的区别
    Java四种线程池的使用
    JSON数据解析
    判断访问浏览器客户端类型(pc,mac,ipad,iphone,android)
    JAVA单线程和多线程的实现方式
    mysql利用st_distance函数查询附近的点的功能
    Redis缓存数据库常见操作
    JAVA获取CLASSPATH路径
  • 原文地址:https://www.cnblogs.com/Blue233333/p/9187770.html
Copyright © 2011-2022 走看看