[CF1037H]Security

Posted greenduck

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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

 

以上是关于[CF1037H]Security的主要内容,如果未能解决你的问题,请参考以下文章

CF1037H Security 线段树合并 SAM

CF1037H Security 后缀自动机 + right集合线段树合并 + 贪心

luoguCF1037H Security

学习算法思想一

学习算法思想一

学习算法思想一