Description
给定一个长度为 (n le 10^6) 的字符串,设删掉第 (i) 个字符后得到的字符串为 (s_i),按照字典序对 (s_1,s_2,...,s_n) 排序。如果两个字符串相等,那么认为编号小的字符串字典序更小。
Solution
对于原串 (a),预处理出对于每一个 (i),最小的 (j>i) 使得 (a_i eq a_j)。
对于 (i<j) 的两个串,如果离 (a_i) 最近的不同的数是 (a_k)。
如果 (j<k),则证明编号为 (i,j) 的两个串完全相同,因此 (i) 排在 (j) 前面。
如果 (j ge k),观察下面的示意图,可以发现,此时 (i) 排在 (j) 前面当且仅当 (a_k < a_i)。
------x--
------x--
i j
-----x--
------x-
至于如何预处理出每个 (i) 对应的 (k),我们只需要倒序暴力递推即可。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1000005;
char a[N];
int f[N],id[N],n;
bool cmp(int i,int j)
{
if(i>j)
{
swap(i,j);
int k=f[i];
if(j<k) return 0;
if(a[k]<a[i]) return 0;
return 1;
}
else
{
int k=f[i];
if(j<k) return 1;
if(a[k]<a[i]) return 1;
return 0;
}
}
signed main()
{
ios::sync_with_stdio(false);
cin>>n>>a+1;
for(int i=1;i<=n;i++) id[i]=i;
f[n+1]=n+1;
for(int i=n;i>=1;--i)
{
if(a[i]!=a[i+1]) f[i]=i+1;
else f[i]=f[i+1];
}
sort(id+1,id+n+1,cmp);
for(int i=1;i<=n;i++)
{
cout<<id[i]<<" ";
}
//system("pause");
}