(SAM)HDU4270 Dynamic Lover

数了一下,在HDU上总共提交了52次……基本上清一色的都是TLE,其中绝大多数的原因是memcpy时没有按照给定的范围,而是莫名其妙的只memcpy了一部分orz……

利用性质:在SAM上沿匹配边不断走就能得到所有子串。

故对题目中的3中操作可以对应于在SAM上进行相应操作。

1、直接继续在SAM上添加字符串即可

2、从根节点开始走最多x(x为给定长度)步,每次向可走的最小处(e.g. a不可走,b可走,就走b)转移。走x步,或者遇到包含当前串的后缀串的结点时结束该过程(某结点是否包含当前串的后缀,只需要在此之前从最后添加字符新得到的结点开始沿着slink边走到根节点并一路标记即可),即得到字典序最小的串。

3、对于删除操作,采用的策略是对每个结点额外记录一个属性,记录该结点是否被删除过。并且记录添加字符串到SAM过程中,某个位置在SAM中的结点编号。由于SAM中某个结点表示一个后缀区间,在往SAM中做添加操作时拆开的点,其对应字符串的结尾是相同的,故其是否被删除过的状态是相同的,为了减少修改操作,将其指向同一个标记数组中的位置即可(用指针、数组记录下标均可)。被删除的点当作无法转移一样处理即可。每次删除只需将连续L个结点修改状态即可,未被删除的结点必定存在某个endpos,满足对应的字符串不包含任何一个被删除的位置。

 

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <vector>
  5 #include <set>
  6 #include <list>
  7 #include <map>
  8 #include <string>
  9 #include <cstring>
 10 #include <stack>
 11 #include <queue>
 12 #include <cmath>
 13 #include <ctime>
 14 #include <bitset>
 15 #include <utility>
 16 #include <complex>
 17 #include <assert.h>
 18 #include <limits.h>
 19 #include <iomanip>
 20 //#include <bits/stdc++.h>
 21 using namespace std;
 22 #define rank rankk
 23 #define mp make_pair
 24 #define pb push_back
 25 #define xo(a,b) ((b)&1?(a):0)
 26 #define tm tmp
 27 
 28 //#define LL ll
 29 typedef unsigned long long ull;
 30 typedef pair<int,int> pii;
 31 typedef long long ll;
 32 typedef pair<ll,int> pli;
 33 typedef pair<int,ll>pil;
 34 typedef pair<ll,ll> pll;
 35 //const double INF=1e20;
 36 const int INF=0x3f3f3f3f;
 37 //const int INF= 0x7fffffff;
 38 //const ll INF=0x3f3f3f3f3f3f3f3fll;
 39 const ll INFF=0x3f3f3f3f3f3f3fll;
 40 //const ll INFF=1e14+5;
 41 const int MAX=2e5+5;
 42 //const ll MAXN=2e8;
 43 //const int MAX_N=MAX;
 44 //const ll MOD=1e9+7;
 45 const ll MOD=998244353;
 46 //const long double pi=acos(-1.0);
 47 //const double eps=0.00000001;
 48 int gcd(int a,int b){return b?gcd(b,a%b):a;}
 49 template<typename T>inline T abs(T a) {return a>0?a:-a;}
 50 //#define double long double
 51 template<class T> inline
 52 void read(T& num) {
 53     bool start=false,neg=false;
 54     char c;
 55     num=0;
 56     while((c=getchar())!=EOF) {
 57         if(c=='-') start=neg=true;
 58         else if(c>='0' && c<='9') {
 59             start=true;
 60             num=num*10+c-'0';
 61         } else if(start) break;
 62     }
 63     if(neg) num=-num;
 64 }
 65 inline ll powMM(ll a,ll b,ll M){
 66     ll ret=1;
 67     a%=M;
 68 //    b%=M;
 69     while (b){
 70         if (b&1) ret=ret*a%M;
 71         b>>=1;
 72         a=a*a%M;
 73     }
 74     return ret;
 75 }
 76 //const long double eps=-1.0;
 77 //clock_t t1 = clock();
 78 //fprintf(stderr, "%ld ms\n", clock() - t1);
 79 void open()
 80 {
 81     freopen("in2.txt","r",stdin);
 82     freopen("out2.txt","w",stdout);
 83 }
 84 
 85 const int MAXL=400005;
 86 const int MAXCH=26;
 87 char s[MAXL],q[MAXL];
 88 const char CH='a';
 89 int tot=0;
 90 int cur_len;
 91 int maxlen[MAXL],trans[MAXL][MAXCH],slink[MAXL],pos[MAXL];
 92 int leftmost[MAXL];
 93 int deled[MAXL];
 94 bool D[MAXL];
 95 int DID;
 96 int bck[MAXL];
 97 
 98 int pe,ID;
 99 inline int new_state(int _maxlen,int *_trans,int _slink)
100 {
101     maxlen[tot]=_maxlen;
102     bck[tot]=0;
103     if(_trans==NULL)
104         memset(trans[tot],-1,sizeof(trans[tot]));
105     else
106         for(int j=0;j<26;j++)trans[tot][j]=_trans[j];
107     slink[tot]=_slink;
108     return tot++;
109 }
110 char ch;
111 inline void add_char()
112 {
113     ++cur_len;
114     int c=ch-CH;
115     int z=new_state(cur_len,NULL,-1);
116     leftmost[z]=cur_len;
117     deled[z]=++DID;
118     D[DID]=0;
119     pos[cur_len]=z;
120     int v=pe;
121     while(v!=-1&&(trans[v][c]==-1||D[deled[trans[v][c]]]))
122     {
123         trans[v][c]=z;
124         v=slink[v];
125     }
126     if(v==-1)
127         slink[z]=0;
128     else
129     {
130         int x=trans[v][c];
131         if(maxlen[v]+1==maxlen[x])
132             slink[z]=x;
133         else
134         {
135             int y=new_state(maxlen[v]+1,trans[x],slink[x]);
136             leftmost[y]=leftmost[x];
137             slink[y]=slink[x];
138             deled[y]=deled[x];
139             slink[x]=y;
140             slink[z]=y;
141             int w=v;
142             while(w!=-1&&trans[w][c]==x)
143             {
144                 trans[w][c]=y;
145                 w=slink[w];
146             }
147         }
148     }
149     pe=z;
150     return;
151 }
152 inline void Del(int len)
153 {
154     while(len--)
155         D[deled[pos[cur_len--]]]=1;
156     pe=pos[cur_len];
157 }
158 inline void col()
159 {
160     int now=pe;
161     while(now>0)
162     {
163         bck[now]=ID;
164         now=slink[now];
165     }
166 }
167 int main()
168 {
169     while(~scanf("%s",s))
170     {
171         DID=tot=pe=ID=0;
172         cur_len=0;
173         int L=strlen(s);
174         pos[0]=0;
175         pe=new_state(0,NULL,-1);
176         for(int i=0;i<L;i++)
177         {
178             ch=s[i];
179             add_char();
180         }
181         int m,k,n;
182         read(m);
183         while(m--)
184         {
185             read(k);
186             if(k==1)
187             {
188                 scanf("%s",s);
189                 int ls=strlen(s);
190                 for(int i=0;i<ls;i++)
191                 {
192                     ch=s[i];
193                     add_char();
194                 }
195             }
196             else if(k==2)
197             {
198                 read(n);
199                 ++ID;
200                 col();
201                 int nowlen,len=n;
202                 int now=0;
203                 for(nowlen=0;;++nowlen)
204                 {
205                     if(nowlen==len)
206                     {
207                         printf("%d\n",leftmost[now]-len+1 );
208                         break;
209                     }
210                     if(bck[now]==ID)
211                     {
212                         printf("%d\n",cur_len-nowlen+1 );
213                         break; ;
214                     }
215                     for(int i=0;i<26;i++)
216                     {
217                         int to=trans[now][i];
218                         if(to!=-1&&!D[deled[to]]){now=to;break;}
219                     }
220                 }
221             }
222             else
223             {
224                 read(n);
225                 Del(n);
226             }
227         }
228     }
229     return 0;
230 }
231 /*
232 bcdacdaa
233 10
234 3 1
235 2 2
236 */

 

转载于:https://www.cnblogs.com/quintessence/p/8886887.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值