做法
对于字符串的第  个字符,定义对偶函数 
,其含义为:对于原串的第 
 个字符,找到它之后与它相同的字符位置 
,结果的第 
 个元素即为 
。如果不存在这样的字符,相应的结果为 
。
就像题中的函数 ,一个字符串的函数 
 就是由每个位置的 
组成。
定义  上的小于关系为字典序从大到小,并且前缀优先。
举例:
按照对偶函数的顺序构造后缀数组即可。
举例:
以串abaabaaaabba为例:
a ba baaaabba abba baabaaaabba abaaaabba abaabaaaabba bba aabba aabaaaabba aaabba aaaabba 答案即为列 。
证明
详细证明见论文 Parameterized Suffix Arrays for Binary Strings。以下大致描述该论文的思路。
我们只需证明, 与 
 存在对应的偏序关系。即 
那么  时显然。下面考虑小于的情况。
如果
是
的前缀,那么
要么是
的前缀,要么把所有
中的
互相代换之后是
的前缀。反之亦然。
证明:
反证。不妨设
那么中必然有一个为
,
中必然没有
。
与 「是
的前缀」相矛盾。
另一侧的证明显然。由此,显然对于任意的
,要么
,要么
。即
要么是
的前缀,要么存在
。
如果
不是
的前缀。那么必然存在
。
记满足的串为
,满足
的串为
。
存在如下没有前缀关系的情况(以下假设):
与
pos 1 2 i-1 i i+1 0 1 1 1 0 0 1 1 1 1 1 1 1 sth>1 or sth 1 1 1 1 1 or sth 可知
与
pos 1 2 ... i-1 i i+1 0 1 ... 1 1 0 0 1 ... 1 1 1 1 1 ... 1 sth>1 or sth 1 1 ... 1 1 1 or x 可知
综上,原命题得证。
时间复杂度
视后缀数组的构造算法, 到 
实现细节
通过令 ,并且加入虚节点 
 的方式,通过普通后缀数组模板实现排序。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=3000020;
char ts[N];
int s[N];
int n,sa[N],rk[N],oldrk[N << 1],id[N],px[N],cnt[N];
bool cmp(int x,int y,int w) 
{
    return oldrk[x] == oldrk[y] && oldrk[x + w] == oldrk[y + w];
}
void solve()
{
    int l[2]={n+1,n+1};
    for(int i=n;i>0;i--)
    {
        s[i]=((l[ts[i]-'a']>n?n:l[ts[i]-'a']-i));
        l[ts[i]-'a']=i;
    }
    n++;
    s[n]=n;
    int i,m=n+3,p,w;
    for(int i=0;i<=n+5;i++)
    {
        sa[i]=rk[i]=oldrk[i]=oldrk[i+n+5]=id[i]=px[i]=cnt[i]=0;
    }
    for(i=1;i<=n;++i) ++cnt[rk[i]=s[i]];
    for(i=1;i<=m;++i) cnt[i]+=cnt[i-1];
    for(i=n;i>=1;--i) sa[cnt[rk[i]]--]=i;
    for(w=1;w<n;w<<=1,m=p) 
    { 
        for(p=0,i=n;i>n-w;--i) id[++p]=i;
        for(i=1;i<=n;++i) if(sa[i]>w) id[++p]=sa[i]-w;
        for(i=0;i<=n;++i) cnt[i]=0;
        for(i=1;i<=n;++i) ++cnt[px[i]=rk[id[i]]];
        for(i=1;i<=m;++i) cnt[i]+=cnt[i-1];
        for(i=n;i>=1;--i) sa[cnt[px[i]]--]=id[i];
        for(i=0;i<=min(N-1,2*n+5);++i) oldrk[i]=rk[i];
        for(p=0,i=1;i<=n;++i) rk[sa[i]]=cmp(sa[i],sa[i-1],w)?p:++p;
    }
    for(i=n-1;i>=1;--i) printf("%d ",sa[i]);
    printf("\n");
}
int main(void)
{
    while(~scanf("%d",&n))
    {
        scanf("%s",ts+1);
        solve();
    }
    return 0;
} 
京公网安备 11010502036488号