Trials Network hdu6704 2019CCPC 1003 K-th occurrence Suffix Array

Question is intended: to give you a string of length n, there is a query q, each interrogation position of a substring s (l, r) of the k-th occurrence, if the number of occurrences of substrings k times less than the output of -1.

Outline of Solution: SA came out first, then the query may be found for each position in all suffixes l by Rank l and [], and then determined that the two half LCP (L, R) comprising S (l, r) the maximum interval [L, R], LCP can by height [] table ST and the determined properties, i.e., [L, R] comprising rank [l], and min {height [L + 1], height [L + 2], ..., height [R]}> = r-l + 1. Now the problem is converted to seek [L, R] k-th large sa [i], this is the classic operated President tree.

This approach feels very easy to come out, but it is to write up some trouble, the SA are not familiar with, then it is easy to write splits.

Chiefs said there was room to listen to the suffix automaton + segment tree merger wording, the first to leave a pit(Not necessarily fill not fill up)

AC Code:

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn=2e5+5;
const int INF=0x3f3f3f3f;

char s[maxn];
int height[maxn],c[maxn],x[maxn],y[maxn],sa[maxn],rk[maxn];
void SA(int n){
    n++;
    int i,j,k,m=128;
    for(i=0;i<m;i++) c[i]=0;
    for(i=0;i<n;i++)c[x[i]=s[i]]++;
    for(i=1;i<m;i++) c[i]+=c[i-1];
    for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
    for(j=1;j<=n;j<<=1){
      k=0;
      for(i=n-j;i<n;i++) y[k++]=i;
      for(i=0;i<n;i++) if(sa[i]>=j) y[k++]=sa[i]-j;
      for(i=0;i<m;i++) c[i]=0;
      for(i=0;i<n;i++) c[x[y[i]]]++;
      for(i=1;i<m;i++) c[i]+=c[i-1];
      for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
      swap(x,y);
      m=0;
      x[sa[0]]=m++;
      for(i=1;i<n;i++){
          if(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+j]==y[sa[i-1]+j]) x[sa[i]]=m-1;
          else x[sa[i]]=m++;
      }
      if(m>=n) break;
    }
    k=0;
    for(i=0;i<n;i++) rk[sa[i]]=i;
    for(i=0;i<n-1;i++){
      if(k) k--;
      j=sa[rk[i]-1];
      while(s[i+k]==s[j+k]) k++;
      height[rk[i]]=k;
    }
    
    
//    cout<<"sa:";for(int i=0;i<n;i++)cout<<sa[i]<<" ";cout<<endl;
//    cout<<"rk:";for(int i=0;i<n;i++)cout<<rk[i]<<" ";cout<<endl;
//    cout<<"h:";for(int i=1;i<n-1;i++)cout<<height[i]<<" ";cout<<endl;
//    
//    for(int i=0;i<n;i++){
//        for(int j=sa[i];j<n;j++)putchar(s[j]);
//        putchar('\n');
//    }
    
}




int n,m;

int mi[maxn][20],lg[maxn];
void initRMQ()
{
    memset(mi,0x3f,sizeof(mi));
    lg[1]=0;
    for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;
    for(int i=1;i<=n;i++)mi[i][0]=height[i]; 
    for(int j=1;j<=lg[n];j++)
        for(int i=1;i<=n;i++)
            mi[i][j]=min(mi[i][j-1],mi[i+(1<<(j-1))][j-1]);
}

int queryRMQ(int x,int y)
{
    int l=min(x,y)+1,r=max(x,y);
    int d=lg[r-l+1];
    //cout<<"llrr:"<<l<<" "<<r<<" "<<min(mi[l][d],mi[r-(1<<d)+1][d])<<endl;
    return min(mi[l][d],mi[r-(1<<d)+1][d]);;
}





int T[maxn],cnt;
int sum[maxn<<5],L[maxn<<5],R[maxn<<5];
inline int build(int l,int r)
{
    int rt=++cnt;
    sum[rt]=0;
    int mid=(l+r)/2;
    if(l<r){
        L[rt]=build(l,mid);
        R[rt]=build(mid+1,r);
    }
    return rt;
}

inline int update(int pre,int l,int r,int x)
{
    int rt=++cnt;
    L[rt]=L[pre];
    R[rt]=R[pre];
    sum[rt]=sum[pre]+1;
    int mid=(l+r)/2;
    if(l<r){
        if(x<=mid)L[rt]=update(L[pre],l,mid,x);
        else R[rt]=update(R[pre],mid+1,r,x);
    }
    return rt;
}

inline int query(int u,int v,int l,int r,int k)
{
    if(l>=r)return l;
    int mid=(l+r)/2;
    int x=sum[L[v]]-sum[L[u]];
    if(x>=k)return query(L[u],L[v],l,mid,k);
    else return query(R[u],R[v],mid+1,r,k-x);
}





int solve(int l,int r,int k)
{
    int len=r-l+1;
    int lp=rk[l],rp=rk[l];
    
    int ll=0,rr=rk[l],mid;
    int mii;
    while(ll<=rr){
        mid=(ll+rr)/2;
        mii=queryRMQ(mid,rk[l]);
        if(mii>=len)lp=mid,rr=mid-1;
        else ll=mid+1;
    }
    
    
    
    ll=rk[l]+1,rr=n;
    while(ll<=rr){
        mid=(ll+rr)/2;
        mii=queryRMQ(rk[l],mid);
        if(mii>=len)rp=mid,ll=mid+1;
        else rr=mid-1;
    }
    
//    cout<<"lr:"<<rk[l]<<" "<<lp<<" "<<rp<<endl;
    
    if(rp-lp+1<k)return -1;
    
    return query(T[lp-1],T[rp],0,n-1,k)+1;
}


int main()
{
//#ifndef ONLINE_JUDGE
//    freopen("in.txt","r",stdin);
//#endif
    int Case;
    scanf("%d",&Case);
    while(Case--){
        scanf("%d %d",&n,&m);
        scanf("%s",s);
        SA(n);
        
        initRMQ();
        
        cnt=0;
        T[0]=build(0,n-1);
        for(int i=1;i<=n;i++)T[i]=update(T[i-1],0,n-1,sa[i]);

        
        int l,r,k;
        while(m--){
            scanf("%d %d %d",&l,&r,&k);
            printf("%d\n",solve(l-1,r-1,k));
        }
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/zengzk/p/11403196.html