【SA】Day 10 提高组模拟C组 T2 找回密码

题目大意

给定一个字符串,求其字典序排名第 k 的子串

解题思路

S A S A M

总之我用了 S A x j b 乱搞就行了

代码

#include<cstdio>
#include<cstring>
#define Il inline
#define re register
#define N 100001
#define r(i,a,b) for(re int i=a;i<=b;i++)
#define d(i,a,b) for(re int i=b;i>=a;i--)
using namespace std;int n,f,t,x[N],wv[N],ws[N],SA[N],y[N],rank[N],height[N];
char s[N];
long long kth;
Il void getsa()
{
    int maxn=0;
    r(i,1,n)
    {
        if(s[i]>96) x[i]=s[i]-96;else
        x[i]=s[i]-65;
        wv[i]=x[i];
        if(wv[i]>maxn) maxn=wv[i];
    }
    r(i,0,maxn) ws[i]=0;
    r(i,1,n) ws[wv[i]]++;
    r(i,1,maxn) ws[i]+=ws[~-i];
    d(i,1,n) SA[ws[wv[i]]]=i,ws[wv[i]]--;
    int l=1,p;
    while(l<=n)
    {
        p=0;
        r(i,n-l+1,n) y[++p]=i;
        r(i,1,n) if(SA[i]>l) y[++p]=SA[i]-l;
        maxn=0;
        r(i,1,n)
        {
            wv[i]=x[y[i]];
            if(wv[i]>maxn) maxn=wv[i];
        }
        r(i,0,maxn) ws[i]=0;
        r(i,1,n) ws[wv[i]]++;
        r(i,1,maxn) ws[i]+=ws[~-i];
        d(i,1,n) SA[ws[wv[i]]]=y[i],ws[wv[i]]--;
        r(i,1,n) y[i]=x[i],x[i]=0;
        p=1;
        x[SA[1]]=1;
        r(i,2,n)
        {
            if(y[SA[~-i]]!=y[SA[i]]||y[SA[~-i]+l]!=y[SA[i]+l]) p++;
            x[SA[i]]=p;
        }
        if(p==n) break;
        l<<=1;
    }
    r(i,1,n) rank[SA[i]]=i;
    return;
}
void getheight()
{
    int k=0,j=0;
    r(i,1,n)
    {
        if(k>0) k--;
        j=SA[~-rank[i]];
        while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k]) k++;
        height[rank[i]]=k;
    }
    return;
}
void getans()
{
    long long now=0;
    f=0;t=0;
    r(i,1,n)
     if(now+n-SA[i]+1-height[i]<kth) now+=n-SA[i]+1-height[i];
     else
     {
        now=kth-now;
        f=SA[i];
        t=SA[i]+height[i]+now-1;
        break;
     }
    if(!f) f=SA[n],t=n;
    return;
}
int main()
{
    scanf("%s\n%lld",s+1,&kth);n=strlen(s+1);
    getsa();
    getheight();
    getans();
    r(i,f,t) putchar(s[i]);//输出
    putchar(10);
}

猜你喜欢

转载自blog.csdn.net/xuxiayang/article/details/81055779