把字符串复制一份,接在原串后面,做一遍后缀数组。后缀数组的排名就是原串的排名,就可以直接用啦。
#include<cstdio>
#include<cstring>
#define MAX 200010
using namespace std;
char s[MAX];
int sa[MAX*2], tsa[MAX*2], rank[MAX*2], trank[MAX*2], sum[MAX*2], n;
void fsort(int j)
{
memset(sum,0,sizeof(sum));
for(int i = 1; i <= n; i++)sum[rank[i+j]]++;
for(int i = 1; i < MAX; i++)sum[i]+=sum[i-1];
for(int i = n; i >= 1; i--)
tsa[sum[rank[i+j]]--]=i;
memset(sum,0,sizeof(sum));
for(int i = 1; i <= n; i++)sum[rank[i]]++;
for(int i = 1; i < MAX; i++)sum[i]+=sum[i-1];
for(int i = n; i >= 1; i--)
sa[sum[rank[tsa[i]]]--]=tsa[i];
}
void work()
{
memset(sum,0,sizeof(sum));
int p;
for(int i = 1; i <= n; i++)trank[i]=int(s[i]);
for(int i = 1; i <= n; i++)sum[trank[i]]++;
for(int i = 1; i < MAX; i++)sum[i]+=sum[i-1];
for(int i = n; i >= 1; i--)
sa[sum[trank[i]]--]=i;
rank[sa[1]]=1;
for(int i = 2, p = 1; i <= n; i++)
{
if(trank[sa[i]]!=trank[sa[i-1]])p++;
rank[sa[i]]=p;
}
for(int j = 1; j <= n; j*=2)
{
fsort(j);
trank[sa[1]]=1;
p=1;
for(int i = 2; i <= n; i++)
{
if(rank[sa[i-1]]!=rank[sa[i]]||rank[sa[i-1]+j]!=rank[sa[i]+j])p++;
trank[sa[i]]=p;
}
for(int i = 1; i <= n ;i++)
rank[i]=trank[i];
}
for(int i = 1; i <= n; i++)
if(sa[i]<=n/2)
printf("%c",s[sa[i]-1]);
}
int main()
{
scanf("%s",s);
s[strlen(s)]=s[0];
n = strlen(s)-1;
for(int i = 1; i <= n; i++)
s[i+n]=s[i];
n<<=1;
work();
return 0;
}