Eighteen suffix array summary of kuangbin topic

The key point of A - Musical Theme
is how to define transposition in code. After analysis, we can use the difference between each point of the sequence and the point in front of it to get a new sequence, then the largest common prefix in this new sequence is the answer.
At the same time, because there cannot be a common part, we need to ensure that the distance between the subscripts of the two points is greater than the length plus 1 when finding the longest common prefix of the new sequence, because we find the longest common prefix of the sequence with the difference as the value, Then, corresponding to the original sequence, it should actually include the point with the obtained subscript -1, so in order to ensure that they cannot overlap, the distance between the two points should be greater than the length plus 1.

#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
using namespace std;
#define rank rk
const int maxn=20005;
int ch[maxn];
int cntA[maxn],cntB[maxn],A[maxn],B[maxn],tsa[maxn],rank[maxn],SA[maxn],height[maxn];
int N;
void get_SA()
{
    for(int i=0; i<=200; i++)cntA[i]=0;
    for(int i=1; i<=N; i++)cntA[ch[i]]++;
    for(int i=1; i<=200; i++)cntA[i]+=cntA[i-1];
    for(int i=N; i>=1; i--)SA[cntA[ch[i]]--]=i;
    rank[SA[1]]=1;
    for(int i=2; i<=N; i++)
    {
        rank[SA[i]]=rank[SA[i-1]];
        if(ch[SA[i]]!=ch[SA[i-1]])
            rank[SA[i]]++;
    }
    for(int step=1;rank[SA[N]]<N;step<<=1)
    {
        for(int i=1;i<=N;i++)cntA[i]=cntB[i]=0;
        for(int i=1;i<=N;i++)
        {
            cntA[A[i]=rank[i]]++;
            cntB[B[i]=(i+step<=N)?rank[i+step]:0]++;
        }
        for(int i=1;i<=N;i++)cntA[i]+=cntA[i-1],cntB[i]+=cntB[i-1];
        for(int i=N;i>=1;i--)tsa[cntB[B[i]]--]=i;
        for(int i=N;i>=1;i--)SA[cntA[A[tsa[i]]]--]=tsa[i];
        rank[SA[1]]=1;
        for(int i=2;i<=N;i++)
        {
            rank[SA[i]]=rank[SA[i-1]];
            if(A[SA[i]]!=A[SA[i-1]]||B[SA[i]]!=B[SA[i-1]])
                rank[SA[i]]++;
        }
    }
}
void get_Height()
{
    int i,j,k=0;
    for(i=1;i<=N;i++)
    {
        if(k)k--;
        j=SA[rank[i]-1];
        while(ch[i+k]==ch[j+k])k++;
        height[rank[i]]=k;
    }
}
int Begin[maxn],cnt;
int minid[maxn],maxid[maxn];
void pre_init(int num)
{
    for(int i=0;i<maxn;i++)minid[i]=N+1,maxid[i]=0;
    cnt=0;
    for(int i=1;i<=N;i++)
    {
        if(height[i]<num)
            Begin[++cnt]=i;
    }
    Begin[++cnt]=N+1;
    for(int i=1;i<cnt;i++)
    {
        for(int j=Begin[i];j<Begin[i+1];j++)
        {
            int theid=SA[j];
            //if(theid==1)continue;
            minid[i]=min(minid[i],theid);
            maxid[i]=max(maxid[i],theid);
        }
    }
}

bool check(int num)
{
    for(int i=1;i<=cnt;i++)
    {
        int themin=minid[i];
        int themax=maxid[i];
        if(themax-themin>=num+1)
            return 1;
    }
    return 0;
}

int main()
{
    while(~scanf("%d",&N)&&N)
    {
        for(int i=1; i<=N; i++)
            scanf("%d",&ch[i]);
        for(int i=N;i>=1;i--)
            ch[i]-=ch[i-1];
        for(int i=1;i<=N;i++)
            ch[i]+=90;
        //cout<<endl;
        get_SA();
        get_Height();

        int l=4,r=N/2;
        int mid,ans=-1;
        while(l<=r)
        {
            mid=l+r>>1;
            pre_init(mid);
            if(check(mid))
            {
                ans=mid;
                l=mid+1;
            }
            else
                r=mid-1;
        }
        printf("%d\n",ans+1);
    }
    return 0;
}

C - Distinct Substrings
finds all distinct substrings.
For each point, let its rank be i, the subscript be idx, and the string length be len. The substring it can provide is len-idx+1 (string subscripts from 1 to len). And it has height[i] with the previous repeated string, so just subtract this.

#include<bits/stdc++.h>
using namespace std;
#define rank rk
const int maxn=1005;
char ch[maxn];
int cntA[maxn],cntB[maxn],A[maxn],B[maxn],tsa[maxn],rank[maxn],SA[maxn],height[maxn];
int n;
void get_SA()
{
    for(int i=0;i<=300;i++)cntA[i]=0;
    for(int i=1;i<=n;i++)cntA[ch[i]]++;
    for(int i=1;i<=300;i++)cntA[i]+=cntA[i-1];
    for(int i=n;i>=1;i--)SA[cntA[ch[i]]--]=i;
    rank[SA[1]]=1;
    for(int i=2;i<=n;i++)
    {
        rank[SA[i]]=rank[SA[i-1]];
        if(ch[SA[i]]!=ch[SA[i-1]])
            rank[SA[i]]++;
    }
    for(int step=1;rank[SA[n]]<n;step<<=1)
    {
        for(int i=0;i<=n;i++)cntA[i]=0,cntB[i]=0;
        for(int i=1;i<=n;i++)
        {
            cntA[A[i]=rank[i]]++;
            cntB[B[i]=(i+step<=n)?rank[i+step]:0]++;
        }
        for(int i=1;i<=n;i++)cntA[i]+=cntA[i-1],cntB[i]+=cntB[i-1];
        for(int i=n;i>=1;i--)tsa[cntB[B[i]]--]=i;
        for(int i=n;i>=1;i--)SA[cntA[A[tsa[i]]]--]=tsa[i];
        rank[SA[1]]=1;
        for(int i=2;i<=n;i++)
        {
            rank[SA[i]]=rank[SA[i-1]];
            if(A[SA[i]]!=A[SA[i-1]]||B[SA[i]]!=B[SA[i-1]])
                rank[SA[i]]++;
        }
    }
}

void get_Height()
{
    int i,j,k=0;
    for(i=1;i<=n;i++)
    {
        if(k)k--;
        j=SA[rank[i]-1];
        while(ch[i+k]==ch[j+k])k++;
        height[rank[i]]=k;
    }
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",ch+1);
        n=strlen(ch+1);
        get_SA();
        get_Height();
        int ans=n-SA[1]+1;
        for(int i=2;i<=n;i++)
        {
            ans+=(n-SA[i]+1-height[i]);
        }
        cout<<ans<<endl;
    }
}

E - Power Strings to
find the smallest loop section.
Before using kmp, there is a conclusion that the minimum loop section is equal to len-next[n], then the number of loops can be judged.
How to do it with suffix array?
The practice is relatively simple, exhaust the length k of the string S, and then judge whether it is satisfied. When judging,
first check whether the length of the string L is divisible by k, and then check whether the longest common
prefix is equal to nk. When asking for the longest common prefix, suffix(1) is fixed, so the RMQ
problem does not need to do all the preprocessing, just need to find
the smallest value between each number in the height array and height[rank[1]] value. The time complexity of the whole approach is O(n).
F - Repeats
finds the repeating substring with the most repetitions.
We can enumerate the length L of repetition. If the repetition length reaches L, then the subscripts are 1, 1+L, 1+2*L.... The two consecutive ones are the same. So we enumerate the subscripts to determine the longest common prefix of the current subscript and subscript + L. In fact, we can go forward, so we reverse the string and find the longest common prefix again, then the two The sum of the lengths of the times is len, k=len/L+1.

#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
#include<math.h>
using namespace std;
#define rank rk
const int maxn=50005;
int ch[2][maxn];
int cntA[2][maxn],cntB[2][maxn],A[2][maxn],B[2][maxn],SA[2][maxn],tsa[2][maxn],rank[2][maxn],Height[2][maxn];
int n;
void get_SA(int idx)
{
    int i;
    for(i=0;i<=2;i++)cntA[idx][i]=0;
    for(i=1;i<=n;i++)cntA[idx][ch[idx][i]]++;
    for(i=1;i<=2;i++)cntA[idx][i]+=cntA[idx][i-1];
    for(i=n;i>=1;i--)SA[idx][cntA[idx][ch[idx][i]]--]=i;
    rank[idx][SA[idx][1]]=1;
    for(i=2;i<=n;i++)
    {
        rank[idx][SA[idx][i]]=rank[idx][SA[idx][i-1]];
        if(ch[idx][SA[idx][i]]!=ch[idx][SA[idx][i-1]])
            rank[idx][SA[idx][i]]++;
    }
    for(int step=1;rank[idx][SA[idx][n]]<n;step<<=1)
    {
        int i;
        for(i=1;i<=n;i++)cntA[idx][i]=0,cntB[idx][i]=0;
        for(i=1;i<=n;i++)
        {
            cntA[idx][A[idx][i]=rank[idx][i]]++;
            cntB[idx][B[idx][i]=(i+step<=n)?rank[idx][i+step]:0]++;
        }
        for(i=1;i<=n;i++)
            cntA[idx][i]+=cntA[idx][i-1],cntB[idx][i]+=cntB[idx][i-1];
        for(i=n;i>=1;i--)
            tsa[idx][cntB[idx][B[idx][i]]--]=i;
        for(i=n;i>=1;i--)
            SA[idx][cntA[idx][A[idx][tsa[idx][i]]]--]=tsa[idx][i];
        rank[idx][SA[idx][1]]=1;
        for(i=2;i<=n;i++)
        {
            rank[idx][SA[idx][i]]=rank[idx][SA[idx][i-1]];
            if(A[idx][SA[idx][i]]!=A[idx][SA[idx][i-1]]||B[idx][SA[idx][i]]!=B[idx][SA[idx][i-1]])
                rank[idx][SA[idx][i]]++;
        }
    }
}

void get_Height(int idx)
{
    int i,j,k=0;
    for(i=1;i<=n;i++)
    {
        if(k)k--;
        j=SA[idx][rank[idx][i]-1];
        while(ch[idx][i+k]==ch[idx][j+k])k++;
        Height[idx][rank[idx][i]]=k;
    }
}
int themin[2][maxn][20];
void RMQ(int idx)
{
    for(int i=1;i<=n;i++)
        themin[idx][i][0]=Height[idx][i];
    for(int j=1;j<20;j++)
        for(int i=1;i<=n;i++)
            if(i+(1<<j)-1<=n)
            {
                themin[idx][i][j]=min(themin[idx][i][j-1],themin[idx][i+(1<<j-1)][j-1]);
            }
}
int qmin(int i,int j,int idx)
{
    int k=log2(j-i+1);
    return min(themin[idx][i][k],themin[idx][j-(1<<k)+1][k]);
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        memset(ch,-1,sizeof(ch));
        //int n;
        scanf("%d",&n);
        char s[3];
        for(int i=1;i<=n;i++)
        {
            scanf("%s",s);
            if(s[0]=='a')ch[0][i]=0;
            else ch[0][i]=1;
        }
        for(int i=n;i>=1;i--)
            ch[1][n-i+1]=ch[0][i];

        /*for(int i=1;i<=n;i++)
            cout<<ch[0][i]<<' ';
        cout<<endl;
        for(int i=1;i<=n;i++)
            cout<<ch[1][i]<<' ';
        cout<<endl;
        */
        get_SA(0);
        get_Height(0);
        RMQ(0);
        get_SA(1);
        get_Height(1);
        RMQ(1);
        int ans=0;
        for(int L=1;L<=n;L++)
        {
            for(int Left=1;Left+L<=n;Left+=L)
            {
                int rk1=rank[0][Left],rk2=rank[0][Left+L];
                int rk3=rank[1][n+1-Left],rk4=rank[1][n+1-(Left+L)];
                int themin1=min(rk1,rk2),themax1=max(rk1,rk2);
                int themin2=min(rk3,rk4),themax2=max(rk3,rk4);
                int len=qmin(themin1+1,themax1,0);
                len+=max(0,qmin(themin2+1,themax2,1)-1);
                ans=max(ans,len/L+1);
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

The question G - Maximum repetition substring
is the same as the question above, but outputs the string with the smallest lexicographical order. We also have to preprocess the rank minimum of each point with rmq. That is, 2 suffix arrays, 3 rmq. But I don't know where to write ugly, and I can't live or die, so I added some judgments that don't need to be calculated.

#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
#include<math.h>
using namespace std;
const int maxn=100005;
#define rank rk
char ch[2][maxn];
int cntA[maxn],cntB[maxn],A[maxn],B[maxn],rank[2][maxn],tsa[maxn],SA[2][maxn],height[2][maxn];
int n;

void get_SA(char *ch,int *rank,int *SA)
{
    for (int i=0;i<=200;i++) cntA[i]=0;
    for (int i=1;i<=n;i++) cntA[ch[i]]++;
    for (int i=1;i<=200;i++) cntA[i]+=cntA[i-1];
    for (int i=n;i>=1;i--) SA[cntA[ch[i]]--] =i;
    rank[SA[1]]=1;
    for (int i=2;i<=n;i++){
        rank[SA[i]]=rank[SA[i-1]];
        if (ch[SA[i]]!=ch[SA[i-1]]) rank[SA[i]]++;
    }
    for (int step = 1;rank[SA[n]]<n;step<<=1){
        for (int i=0;i<=n;i++)cntA[i]=cntB[i]=0;
        for (int i=1;i<=n;i++){
            cntA[A[i]=rank[i]]++;
            cntB[B[i]=(i+step<=n)?rank[i+step]:0]++;
        }
        for (int i=1;i<=n;i++) cntA[i]+=cntA[i-1],cntB[i]+=cntB[i-1];
        for (int i=n;i>=1;i--) tsa[cntB[B[i]]--] =i;
        for (int i=n;i>=1;i--) SA[cntA[A[tsa[i]]]--] = tsa[i];
        rank[SA[1]]=1;
        for (int i=2;i<=n;i++){
            rank[SA[i]]=rank[SA[i-1]];
            if (A[SA[i]]!=A[SA[i-1]]||B[SA[i]]!=B[SA[i-1]]) rank[SA[i]]++;
        }
    }
}

void get_Height(char *ch,int *rank,int *SA,int *height)
{
    int i,j,k=0;
    for(i=1;i<=n;i++)
    {
        if(k)k--;
        j=SA[rank[i]-1];
        while(ch[i+k]==ch[j+k])k++;
        height[rank[i]]=k;
    }
}
int minheight[2][maxn][20];
int minrank[maxn][20];
void RMQ(int (&minsum)[maxn][20],int *height)
{
    for(int i=1;i<=n;i++)
        minsum[i][0]=height[i];
    int k=log2(n);
    for(int j=1;j<=k;j++)
        for(int i=1;i<=n;i++)
            if(i+(1<<j)-1<=n)
            minsum[i][j]=min(minsum[i][j-1],minsum[i+(1<<(j-1))][j-1]);
}
int qmin(int a,int b,int (&minsum)[maxn][20])
{
    int k=log2(b-a+1);
    return min(minsum[a][k],minsum[b-(1<<k)+1][k]);
}

int queryLen(int rk1,int rk2,int (&minsum)[maxn][20])
{
    if(rk1>rk2)swap(rk1,rk2);
    return qmin(rk1+1,rk2,minsum);

}

int main()
{
    int cas=1;
    while(~scanf("%s",ch[0]+1)&&ch[0][1]!='#')
    {
        n=strlen(ch[0]+1);
        for(int i=n;i>=1;i--)
            ch[1][n-i+1]=ch[0][i];
        get_SA(ch[0],rank[0],SA[0]);
        get_Height(ch[0],rank[0],SA[0],height[0]);
        get_SA(ch[1],rank[1],SA[1]);
        get_Height(ch[1],rank[1],SA[1],height[1]);
        RMQ(minheight[0],height[0]);
        RMQ(minheight[1],height[1]);
        RMQ(minrank,rank[0]);
        int theminrank=n+1;
        int maxk=0;
        int thelen;
        for(int L=1;L<=n/2;L++)
        {
            int times=n/L;
            if(L!=1)times--;
            for(int j=0;j<times;j++)
            {
                int now_lc=j*L+1;
                if(ch[0][now_lc]!=ch[0][now_lc+L]&&L!=1)continue;
                int rightlen=queryLen(rank[0][now_lc],rank[0][now_lc+L],minheight[0]);
                int leftlen=queryLen(rank[1][n+1-now_lc],rank[1][n+1-now_lc-L],minheight[1]);
                int len=leftlen+rightlen;
                if(len)len--;
                int k=len/L+1;
                if(k==1&&L!=1)continue;
                int lidx,ridx;
                if(k==1)
                    lidx=ridx=now_lc;
                else
                {
                    lidx=now_lc-leftlen+1;
                    ridx=now_lc+L-k*L+rightlen;
                }
                int min_rank=qmin(lidx,ridx,minrank);
                if(k>maxk)
                {
                    maxk=k;
                    theminrank=min_rank;
                    thelen=L;
                }
                else if(k==maxk)
                {
                    if(min_rank<theminrank)
                    {
                        theminrank=min_rank;
                        thelen=L;
                    }
                }
            }
        }
        printf("Case %d: ",cas++);
        for(int i=1;i<=maxk;i++)
        {
            for(int j=SA[0][theminrank];j<SA[0][theminrank]+thelen;j++)
                printf("%c",ch[0][j]);
        }
        puts("");
    }
    return 0;
}

I - Common Substrings
Find the lengths of all consecutive identical substrings of A and B.
We can connect the two strings, add a symbol that has not appeared in the middle, and after suffixing the array, the current problem can be converted into, set the subscript of A as i and the subscript of B as j, find the height[rank [i]] to the minimum value of height[rank[j]], which is their common prefix, if enumeration i and j must time out.
At this time, we can use a monotonic stack to calculate the longest prefix of a subscript A and all occurrences of B before it. Because the longest prefix of the two subscripts is the minimum value of the height between the two subscript rankings, it has a monotonicity. All values ​​larger than it in the stack will be popped out and replaced by it, so we need to maintain Two values, one is the value of height in the stack, and the other is the number of all elements in the stack.

#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
using namespace std;
#define rank rk
#define stack stk
const int maxn=100005;
char x[maxn],y[maxn];
char ch[maxn*2];
int cntA[maxn*2],cntB[maxn*2],A[maxn*2],B[maxn*2],tsa[maxn*2],rank[maxn*2],SA[maxn*2],Height[maxn*2];
int n;
typedef long long ll;
void get_SA()
{
    for (int i=0;i<=300;i++) cntA[i]=0;
    for (int i=1;i<=n;i++) cntA[ch[i]]++;
    for (int i=1;i<=300;i++) cntA[i]+=cntA[i-1];
    for (int i=n;i>=1;i--) SA[cntA[ch[i]]--] =i;
    rank[SA[1]]=1;
    for (int i=2;i<=n;i++){
        rank[SA[i]]=rank[SA[i-1]];
        if (ch[SA[i]]!=ch[SA[i-1]]) rank[SA[i]]++;
    }
    for (int step = 1;rank[SA[n]]<n;step<<=1){
        for (int i=0;i<=n;i++)cntA[i]=cntB[i]=0;
        for (int i=1;i<=n;i++){
            cntA[A[i]=rank[i]]++;
            cntB[B[i]=(i+step<=n)?rank[i+step]:0]++;
        }
        for (int i=1;i<=n;i++) cntA[i]+=cntA[i-1],cntB[i]+=cntB[i-1];
        for (int i=n;i>=1;i--) tsa[cntB[B[i]]--] =i;
        for (int i=n;i>=1;i--) SA[cntA[A[tsa[i]]]--] = tsa[i];
        rank[SA[1]]=1;
        for (int i=2;i<=n;i++){
            rank[SA[i]]=rank[SA[i-1]];
            if (A[SA[i]]!=A[SA[i-1]]||B[SA[i]]!=B[SA[i-1]]) rank[SA[i]]++;
        }
    }

}

void get_Height()
{
    int i,j,k=0;
    for(i=1;i<=n;i++)
    {
        if(k)k--;
        j=SA[rank[i]-1];
        while(ch[i+k]==ch[j+k])k++;
        Height[rank[i]]=k;
    }
}
int stack[maxn*2],tot;
ll cnt[maxn*2],sum,ans;
int main()
{
    int K;
    while(~scanf("%d",&K)&&K)
    {
        memset(cnt,0,sizeof(cnt));
        ans=0;
        scanf("%s %s",x,y);
        int now=1;
        int len1=strlen(x);
        for(int i=0;i<len1;i++,now++)
            ch[now]=x[i];
        ch[now++]='$';
        int len2=strlen(y);
        for(int i=0;i<len2;i++,now++)
            ch[now]=y[i];
        n=now-1;
        get_SA();
        get_Height();
        int num;
        for(int i=1;i<=n;i++)
        {
            if(Height[i]<K)
            {
                sum=0;
                tot=0;
                continue;
            }
            num=0;
            while(tot&&stack[tot]>Height[i])
            {
                sum-=1LL*cnt[tot]*(stack[tot]-K+1);
                sum+=1LL*cnt[tot]*(Height[i]-K+1);
                num+=cnt[tot];
                tot--;
            }
            stack[++tot]=Height[i];
            if(SA[i-1]<=len1)
                cnt[tot]=num;
            else
                cnt[tot]=num+1,sum+=(Height[i]-K+1);
            if(SA[i]<=len1)
                ans+=sum;
        }
        for(int i=1;i<=n;i++)
        {
            if(Height[i]<K)
            {
                sum=0;
                tot=0;
                continue;
            }
            num=0;
            while(tot&&stack[tot]>Height[i])
            {
                sum-=1LL*cnt[tot]*(stack[tot]-K+1);
                sum+=1LL*cnt[tot]*(Height[i]-K+1);
                num+=cnt[tot];
                tot--;
            }
            stack[++tot]=Height[i];
            if(SA[i-1]>len1)
                cnt[tot]=num;
            else
                cnt[tot]=num+1,sum+=(Height[i]-K+1);
            if(SA[i]>len1)
                ans+=sum;
        }
        cout<<ans<<endl;
    }

    return 0;

}

The question of N - Sequence
is a bit strange, the data range is not given, but it is undoubtedly a good question. Since the data range is not given, the title requires us to discretize the data.
Let's talk about how to do this question, the topic stipulates A1>A2,....,An , so we reverse this string, and then find the suffix array, the corresponding subscript with the smallest ranking is the first paragraph. What about the second and third paragraphs?
Why can't I think of this approach?
After selecting the first paragraph, copy the remaining strings to the end, and then find the suffix array once, and find the smallest ranking and the subscript within the range of the remaining strings.
After this operation, the obtained string is the required string, and you can write and understand it yourself.

#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
using namespace std;
#define rank rk
const int maxn=200005;
int a[maxn],b[maxn];
int ch[maxn];
int cntA[maxn],cntB[maxn],A[maxn],B[maxn],SA[maxn],tsa[maxn],rank[maxn],height[maxn];
int n;
void get_SA()
{
    for (int i=0;i<maxn;i++) cntA[i]=0;
    for (int i=1;i<=n;i++) cntA[ch[i]]++;
    for (int i=1;i<maxn;i++) cntA[i]+=cntA[i-1];
    for (int i=n;i>=1;i--) SA[cntA[ch[i]]--] =i;
    rank[SA[1]]=1;
    for (int i=2;i<=n;i++){
        rank[SA[i]]=rank[SA[i-1]];
        if (ch[SA[i]]!=ch[SA[i-1]]) rank[SA[i]]++;
    }
    for (int step = 1;rank[SA[n]]<n;step<<=1){
        for (int i=0;i<=n;i++)cntA[i]=cntB[i]=0;
        for (int i=1;i<=n;i++){
            cntA[A[i]=rank[i]]++;
            cntB[B[i]=(i+step<=n)?rank[i+step]:0]++;
        }
        for (int i=1;i<=n;i++) cntA[i]+=cntA[i-1],cntB[i]+=cntB[i-1];
        for (int i=n;i>=1;i--) tsa[cntB[B[i]]--] =i;
        for (int i=n;i>=1;i--) SA[cntA[A[tsa[i]]]--] = tsa[i];
        rank[SA[1]]=1;
        for (int i=2;i<=n;i++){
            rank[SA[i]]=rank[SA[i-1]];
            if (A[SA[i]]!=A[SA[i-1]]||B[SA[i]]!=B[SA[i-1]]) rank[SA[i]]++;
        }
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        b[i]=a[i];
    }
    sort(a+1,a+1+n);
    int len=unique(a+1,a+1+n)-a-1;
    for(int i=1;i<=n;i++)
    {
        int tmp=lower_bound(a+1,a+1+len,b[n-i+1])-a;
        ch[i]=tmp;
    }
    get_SA();
    int minrank=n+1;
    int minidx;
    for(int i=3;i<=n;i++)
    {
        if(minrank>rank[i])
        {
            minrank=rank[i];
            minidx=i;
        }
    }
    for(int i=minidx;i<=n;i++)
        printf("%d\n",a[ch[i]]);
    for(int i=minidx;i<=2*minidx-2;i++)
        ch[i]=ch[i-minidx+1];
    n=2*minidx-2;
    get_SA();
    for(int i=1;i<=2*minidx-2;i++)
    {
        if(SA[i]<=minidx-1&&SA[i]!=1)
        {
            int thisidx=SA[i];
            for(int j=thisidx;j<thisidx+minidx-1;j++)
                printf("%d\n",a[ch[j]]);
            break;
        }
    }
    return 0;
}

I don't know why, but writing questions is getting more and more inconvenient. I am writing questions every day but I feel more and more disheartened. . In any case, you still have to finish the kuangbin topic.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324779184&siteId=291194637