[CF1037H]Security

The meaning of problems

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


 

Think

Greedy idea is to read as much as possible to find the string section of the prefix, and then one more for lexicographical relatively large characters.

First establish the original string SAM, taking into account the range limitations, the need to merge tree line maintenance endpos collection.

For an inquiry, we now find its prefix corresponding node on SAM. If there is, continue; otherwise, no need to look anymore. This process back then, whenever a node appears greater than the current character of the side, directly output the answer.

Time complexity $ O (26 * n * logn) $.


 

Code

  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

 

Guess you like

Origin www.cnblogs.com/GreenDuck/p/11409433.html