码迷,mamicode.com
首页 > 其他好文 > 详细

[CF1037H]Security

时间:2019-08-25 21:43:27      阅读:136      评论:0      收藏:0      [点我收藏+]

标签:inline   problem   play   gif   cin   ==   前缀   dde   复杂度   

题意

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

标签:inline   problem   play   gif   cin   ==   前缀   dde   复杂度   

原文地址:https://www.cnblogs.com/GreenDuck/p/11409433.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!