HDU - 6704 K-th occurrence (+ suffix array President tree / suffix tree automata combined + multiplication + segment)

Question is intended: to give you a string of n and m sets of query, asking each given l, r, k, find s [l, r] k-th point of the left appears.

Solution one:

Suffix array is obtained, the ranking of the Chairman tree construction, for each set of query-half or multiplying President tree identify corresponding left and right end points, find the k subscript to large.

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N=1e5+10,mod=998244353;
 5 char buf[N];
 6 int s[N],sa[N],buf1[N],buf2[N],c[N],n,rnk[N],ht[N],ST[N][20],Log[N],m;
 7 void Sort(int* x,int* y,int m) {
 8     for(int i=0; i<m; ++i)c[i]=0;
 9     for(int i=0; i<n; ++i)++c[x[i]];
10     for(int i=1; i<m; ++i)c[i]+=c[i-1];
11     for(int i=n-1; i>=0; --i)sa[--c[x[y[i]]]]=y[i];
12 }
13 void da(int* s,int n,int m=1000) {
14     int *x=buf1,*y=buf2;
15     x[n]=y[n]=-1;
16     for(int i=0; i<n; ++i)x[i]=s[i],y[i]=i;
17     Sort(x,y,m);
18     for(int k=1; k<n; k<<=1) {
19         int p=0;
20         for(int i=n-k; i<n; ++i)y[p++]=i;
21         for(int i=0; i<n; ++i)if(sa[i]>=k)y[p++]=sa[i]-k;
22         Sort(x,y,m),p=1,y[sa[0]]=0;
23         for(int i=1; i<n; ++i)y[sa[i]]=x[sa[i-1]]==x[sa[i]]&&x[sa[i-1]+k]==x[sa[i]+k]?p-1:p++;
24         if(p==n)break;
25         swap(x,y),m=p;
26     }
27 }
28 void getht() {
29     for(int i=0; i<n; ++i)rnk[sa[i]]=i;
30     ht[0]=0;
31     for(int i=0,k=0; i<n; ++i) {
32         if(k)--k;
33         if(!rnk[i])continue;
34         for(; s[i+k]==s[sa[rnk[i]-1]+k]; ++k);
35         ht[rnk[i]]=k;
36     }
37 }
38 void initST() {
39     for(int i=1; i<n; ++i)ST[i][0]=ht[i];
40     for(int j=1; (1<<j)<=n; ++j)
41         for(int i=1; i+(1<<j)-1<n; ++i)
42             ST[i][j]=min(ST[i][j-1],ST[i+(1<<(j-1))][j-1]);
43 }
44 int lcp(int l,int r) {
45     if(l==r)return n-sa[l];
46     if(l>r)swap(l,r);
47     l++;
48     int k=Log[r-l+1];
49     return min(ST[l][k],ST[r-(1<<k)+1][k]);
50 }
51 int rt[N],ls[N*30],rs[N*30],sum[N*30],tot;
52 #define mid ((l+r)>>1)
53 int cpy(int v) {int u=++tot; ls[u]=ls[v],rs[u]=rs[v],sum[u]=sum[v]; return u;}
54 void upd(int& u,int v,int p,int l=0,int r=n-1) {
55     u=cpy(v);
56     sum[u]++;
57     if(l==r)return;
58     p<=mid?upd(ls[u],ls[v],p,l,mid):upd(rs[u],rs[v],p,mid+1,r);
59 }
60 int qry(int u,int v,int k,int l=0,int r=n-1) {
61     if(l==r)return l;
62     int cnt=sum[ls[u]]-sum[ls[v]];
63     return k<=cnt?qry(ls[u],ls[v],k,l,mid):qry(rs[u],rs[v],k-cnt,mid+1,r);
64 }
65 void build() {
66     da(s,n),getht(),initST();
67     tot=0;
68     for(int i=1; i<=n; ++i)upd(rt[i],rt[i-1],sa[i-1]);
69 }
70 int main() {
71     Log[0]=-1;
72     for(int i=1; i<N; ++i)Log[i]=Log[i>>1]+1;
73     int T;
74     for(scanf("%d",&T); T--;) {
75         scanf("%d%d%s",&n,&m,buf);
76         for(int i=0; i<n; ++i)s[i]=buf[i];
77         s[n]=0;
78         build();
79         while(m--) {
80             int l,r,k;
81             scanf("%d%d%d",&l,&r,&k);
82             l--,r--;
83             int L,R,M=rnk[l],len=r-l+1;
84             L=R=M;
85             for(int i=Log[n]; i>=0; --i)if(L-(1<<i)>=0&&lcp(M,L-(1<<i))>=len)L-=(1<<i);
86             for(int i=Log[n]; i>=0; --i)if(R+(1<<i)<n&&lcp(M,R+(1<<i))>=len)R+=(1<<i);
87             printf("%d\n",k<=sum[rt[R+1]]-sum[rt[L]]?qry(rt[R+1],rt[L],k)+1:-1);
88         }
89     }
90     return 0;
91 }

Solution two:

Establishing a suffix automaton, on suffix trees (fail tree) can be obtained for the entire segment tree merge right value of each node included. Query strings to be found multiplying the corresponding sub-node for each query, the query tree and the k-th segment can be large.

Persistence may merge the query can be achieved online.

fail tree dfs order to build a sustainable segment of the tree looks like it may be (how this sentence so familiar?)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N=2e5+10,M=26;
 5 char s[N];
 6 int n,m,fa[N],go[N][M],mxl[N],last,tot,samrt[N],c[N],ss[N],Fa[N][20];
 7 int rt[N],ls[N*50],rs[N*50],sum[N*50],tot2;
 8 #define mid ((l+r)>>1)
 9 int cpy(int v) {int u=++tot2; ls[u]=ls[v],rs[u]=rs[v],sum[u]=sum[v]; return u;}
10 void upd(int& u,int v,int p,int l=1,int r=n) {
11     u=cpy(v),sum[u]++;
12     if(l==r)return;
13     p<=mid?upd(ls[u],ls[v],p,l,mid):upd(rs[u],rs[v],p,mid+1,r);
14 }
15 void mg(int& w,int u,int v) {
16     if(!u||!v) {w=u|v; return;}
17     w=cpy(u),sum[w]+=sum[v];
18     mg(ls[w],ls[u],ls[v]),mg(rs[w],rs[u],rs[v]);
19 }
20 int qry(int u,int k,int l=1,int r=n) {
21     if(l==r)return l;
22     return k<=sum[ls[u]]?qry(ls[u],k,l,mid):qry(rs[u],k-sum[ls[u]],mid+1,r);
23 }
24 int newnode(int l) {int u=++tot; rt[u]=0,mxl[u]=l,memset(go[u],0,sizeof go[u]); return u;}
25 void add(int ch,int r) {
26     int p=last,np=last=newnode(mxl[p]+1);
27     samrt[r]=np;
28     upd(rt[np],rt[np],r,1);
29     for(; p&&!go[p][ch]; p=fa[p])go[p][ch]=np;
30     if(!p)fa[np]=1;
31     else {
32         int q=go[p][ch];
33         if(mxl[q]==mxl[p]+1)fa[np]=q;
34         else {
35             int nq=newnode(mxl[p]+1);
36             memcpy(go[nq],go[q],sizeof go[q]);
37             fa[nq]=fa[q],fa[q]=fa[np]=nq;
38             for(; p&&go[p][ch]==q; p=fa[p])go[p][ch]=nq;
39         }
40     }
41 }
42 void build() {
43     tot=tot2=0,last=newnode(0);
44     for(int i=0; i<n; ++i)add(s[i]-'a',i+1);
45     for(int i=0; i<=tot; ++i)c[i]=0;
46     for(int i=1; i<=tot; ++i)++c[mxl[i]];
47     for(int i=1; i<=tot; ++i)c[i]+=c[i-1];
48     for(int i=1; i<=tot; ++i)ss[--c[mxl[i]]]=i;
49     for(int i=tot-1; i>0; --i)mg(rt[fa[ss[i]]],rt[fa[ss[i]]],rt[ss[i]]);
50     for(int i=1; i<=tot; ++i)Fa[i][0]=fa[i];
51     for(int k=1; k<20; ++k)for(int i=1; i<=tot; ++i)Fa[i][k]=Fa[Fa[i][k-1]][k-1];
52 }
53 int main() {
54     int T;
55     for(scanf("%d",&T); T--;) {
56         scanf("%d%d%s",&n,&m,s);
57         build();
58         while(m--) {
59             int l,r,k;
60             scanf("%d%d%d",&l,&r,&k);
61             int u=samrt[r],len=r-l+1;
62             if(mxl[fa[u]]+1>len) {
63                 for(int k=19; k>=0; --k)if(mxl[fa[Fa[u][k]]]+1>len)u=Fa[u][k];
64                 u=fa[u];
65             }
66             printf("%d\n",k<=sum[rt[u]]?qry(rt[u],k)-len+1:-1);
67         }
68     }
69     return 0;
70 }

 

Guess you like

Origin www.cnblogs.com/asdfsag/p/11515433.html