• [CF1037H]Security


    题意

    https://codeforces.com/contest/1037/problem/H


     

    思考

    贪心的思路是,尽可能多地找到读入串的一段前缀,然后再添上一个字典序比较大的字符。

    先对原串建立SAM,考虑到有区间限制,需线段树合并维护endpos集合。

    对于一个询问,我们现在SAM上找对它的前缀对应的节点。若存在,继续;否则就没必要找下去了。然后回溯这个过程,只要某个节点处出现大于当前字符的出边,直接输出答案。

    时间复杂度$O(26*n*logn)$。


     

    代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=1E5+5;
      4 int n;
      5 int size,head[maxn*4];
      6 int cnt,root[maxn*40],ls[maxn*40],rs[maxn*40],ans[maxn*40],what[maxn*40];
      7 struct edge
      8 {
      9     int to,next;
     10 }E[maxn*2];
     11 inline void addE(int u,int v)
     12 {
     13     E[++size].to=v;
     14     E[size].next=head[u];
     15     head[u]=size;
     16 }
     17 struct tree
     18 {
     19     int fa,len,ch[26];
     20 };
     21 void out(int l,int r,int num)
     22 {
     23     if(l==r)
     24     {
     25         cout<<l<<" ";
     26         return;
     27     }
     28     int mid=(l+r)>>1;
     29     if(ls[num])
     30         out(l,mid,ls[num]);
     31     if(rs[num])
     32         out(mid+1,r,rs[num]); 
     33 }
     34 void insertT(int l,int r,int pos,int&num,int pre)
     35 {
     36     num=++cnt;
     37     ls[num]=ls[pre],rs[num]=rs[pre];
     38     if(l==r)
     39     {
     40         ans[num]=pos;
     41         return;
     42     }
     43     int mid=(l+r)>>1;
     44     if(pos<=mid)
     45         insertT(l,mid,pos,ls[num],ls[pre]);
     46     else
     47         insertT(mid+1,r,pos,rs[num],rs[pre]);
     48     ans[num]=max(ans[ls[num]],ans[rs[num]]);
     49 }
     50 int merge(int l,int r,int a,int b)
     51 {
     52     if(!a||!b)
     53         return a|b;
     54     int num=++cnt;
     55     ans[num]=max(ans[a],ans[b]);
     56     if(l==r)
     57         return num;
     58     int mid=(l+r)>>1;
     59     ls[num]=merge(l,mid,ls[a],ls[b]);
     60     rs[num]=merge(mid+1,r,rs[a],rs[b]);
     61     ans[num]=max(ans[ls[num]],ans[rs[num]]);
     62     return num;
     63 }
     64 int ask(int L,int R,int l,int r,int num)
     65 {
     66     if(!num)
     67         return 0;
     68     if(L<=l&&r<=R)
     69         return ans[num];
     70     int mid=(l+r)>>1;
     71     if(R<=mid)
     72         return ask(L,R,l,mid,ls[num]);
     73     else if(mid<L)
     74         return ask(L,R,mid+1,r,rs[num]);
     75     return max(ask(L,R,l,mid,ls[num]),ask(L,R,mid+1,r,rs[num]));
     76 }
     77 void dfs(int u)
     78 {
     79     for(int i=head[u];i;i=E[i].next)
     80     {
     81         int v=E[i].to;
     82         dfs(v);
     83         root[u]=merge(1,n,root[u],root[v]);
     84     }
     85     if(what[u])
     86         insertT(1,n,what[u],root[u],root[u]);
     87 }
     88 struct SAM
     89 {
     90     tree t[maxn*2];
     91     int last,tot;
     92     SAM()
     93     {
     94         last=tot=1;
     95     }
     96     inline void add(int x,int pos)
     97     {
     98         int u=last,now=++tot;
     99         last=tot;
    100         what[now]=pos;
    101         t[now].len=t[u].len+1;
    102         for(;u&&!t[u].ch[x];u=t[u].fa)
    103             t[u].ch[x]=now;
    104         if(!u)
    105             t[now].fa=1;
    106         else
    107         {
    108             int v=t[u].ch[x];
    109             if(t[v].len==t[u].len+1)
    110                 t[now].fa=v;
    111             else
    112             {
    113                 int w=++tot;
    114                 t[w]=t[v];
    115                 t[w].len=t[u].len+1;
    116                 t[now].fa=t[v].fa=w;
    117                 for(;u&&t[u].ch[x]==v;u=t[u].fa)
    118                     t[u].ch[x]=w;
    119             }
    120         }
    121     }
    122     void build()
    123     {
    124         for(int i=2;i<=tot;++i)
    125             addE(t[i].fa,i);
    126     }
    127 }T;
    128 int wait[maxn*2];
    129 void solve()
    130 {
    131     int L,R;
    132     string str;
    133     cin>>L>>R>>str;
    134     int pos=1,top=0; 
    135     wait[top++]=pos;
    136     for(int i=0;i<str.size();++i)
    137     {
    138         int x=str[i]-'a';
    139         if(T.t[pos].ch[x])
    140         {
    141             pos=T.t[pos].ch[x];
    142             x=ask(L,R,1,n,root[pos]);
    143             if(x-i<L)
    144                 break;
    145             wait[top++]=pos;
    146         }
    147         else
    148             break;
    149     }
    150     for(int i=top-1;i>=0;--i)
    151     {
    152         int x=max(str[i]-'a',-1);
    153         for(int j=x+1;j<26;++j)
    154             if(T.t[wait[i]].ch[j])
    155             {
    156                 int pos=T.t[wait[i]].ch[j];
    157                 int x=ask(L,R,1,n,root[pos]);
    158                 if(x-i>=L)
    159                 {
    160                     for(int k=0;k<i;++k)
    161                         cout<<str[k];
    162                     cout<<char('a'+j)<<endl;
    163                     return;
    164                 }
    165             }
    166     }
    167     cout<<-1<<endl;
    168 }
    169 int main()
    170 {
    171     ios::sync_with_stdio(false);
    172     string str;
    173     cin>>str;
    174     n=str.size();
    175     for(int i=0;i<str.size();++i)
    176         T.add(str[i]-'a',i+1);
    177     T.build();
    178     dfs(1);
    179     int T;
    180     cin>>T;
    181     while(T--)
    182         solve();
    183     return 0;
    184 }
    View Code
  • 相关阅读:
    【hdu 2569】ACM程序设计期末考试081230
    【信息安全111班暑期学习工作任务】
    【hdu 1698 Just a Hook(被搞死)】
    Win8下安装 .net framework 3.5.1 无需连网安装方法,证实有效
    【UVA 488 Triangle Wave】
    【As Easy As A+B 专题训练排序】
    【hdu 1787 GCD Again (数论、欧拉函数)】
    【hdu 2602 Bone Collector(动态规划、01背包)】
    【poj 1953 World Cup Noise】
    【poj 2478 Farey Sequence (欧拉函数、数论)】
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/11409433.html
Copyright © 2020-2023  润新知