1.
首
先
我
们
发
现
每
个
后
缀
开
头
一
定
是
0
,
而
且
开
头
都
是
0..
[
若
干
个
1
]
.
.
0
这
种
格
式
,
按
照
字
典
序
的
排
序
方
式
那
么
如
果
两
个
0
之
间
的
1
越
少
字
典
序
就
越
小
。
例
如
a
a
a
a
a
b
=
>
011110
,
a
a
a
b
=
>
0110
,
那
么
我
们
设
d
i
s
[
i
]
就
是
第
i
位
开
始
的
往
后
延
申
有
多
少
个
是
和
开
头
字
母
相
同
的
,
如
a
a
a
b
=
>
d
i
s
[
]
=
{
3
,
2
,
1
,
1
}
;
那
么
d
i
s
[
i
]
越
小
对
应
数
组
的
字
典
序
一
定
越
小
1.首先我们发现每个后缀开头一定是0,而且开头都是0..[若干个1]..0这种格式,按照字典序的排序方式那么如果两个0之间的1越少字典序就越小。例如aaaaab=>011110,aaab=>0110,那么我们设dis[i]就是第i位开始的往后延申有多少个是和开头字母相同的,如aaab=>dis[]=\{3,2,1,1\};那么dis[i]越小对应数组的字典序一定越小
1.首先我们发现每个后缀开头一定是0,而且开头都是0..[若干个1]..0这种格式,按照字典序的排序方式那么如果两个0之间的1越少字典序就越小。例如aaaaab=>011110,aaab=>0110,那么我们设dis[i]就是第i位开始的往后延申有多少个是和开头字母相同的,如aaab=>dis[]={3,2,1,1};那么dis[i]越小对应数组的字典序一定越小
2.
还
有
一
个
明
显
的
规
律
就
是
0
的
个
数
最
多
两
个
,
因
为
出
现
了
两
个
0
说
明
a
b
和
字
母
已
经
完
全
出
现
了
,
后
面
字
母
的
B
[
]
数
组
的
值
就
不
变
了
,
那
么
我
们
可
以
对
整
个
串
求
一
遍
B
[
]
数
组
,
在
比
较
两
个
后
缀
的
时
候
:
我
们
先
比
较
d
i
s
[
i
]
和
d
i
s
[
j
]
,
如
果
d
i
s
[
i
]
=
=
d
i
s
[
j
]
那
么
我
们
就
比
较
后
面
的
一
截
,
根
据
字
典
序
的
定
义
比
较
第
一
个
不
相
同
的
位
置
就
可
以
了
,
那
么
我
们
就
要
求
i
+
d
i
s
[
i
]
和
j
+
d
i
s
[
j
]
后
面
的
l
c
p
,
比
较
B
[
i
+
l
c
p
+
d
i
s
[
i
]
]
和
B
[
j
+
l
c
p
+
d
i
s
[
j
]
]
就
可
以
了
2.还有一个明显的规律就是0的个数最多两个,因为出现了两个0说明ab和字母已经完全出现了,后面字母的B[]数组的值就不变了,那么我们可以对整个串求一遍B[]数组,在比较两个后缀的时候:我们先比较dis[i]和dis[j],如果dis[i]==dis[j]那么我们就比较后面的一截,根据字典序的定义比较第一个不相同的位置就可以了,那么我们就要求i+dis[i]和j+dis[j]后面的lcp,比较B[i+lcp+dis[i]]和B[j+lcp+dis[j]]就可以了
2.还有一个明显的规律就是0的个数最多两个,因为出现了两个0说明ab和字母已经完全出现了,后面字母的B[]数组的值就不变了,那么我们可以对整个串求一遍B[]数组,在比较两个后缀的时候:我们先比较dis[i]和dis[j],如果dis[i]==dis[j]那么我们就比较后面的一截,根据字典序的定义比较第一个不相同的位置就可以了,那么我们就要求i+dis[i]和j+dis[j]后面的lcp,比较B[i+lcp+dis[i]]和B[j+lcp+dis[j]]就可以了
3.
注
意
还
有
就
是
i
+
d
i
s
[
i
]
会
大
于
n
,
大
于
n
相
当
于
后
面
补
0
,
在
前
面
相
同
的
情
况
下
越
短
的
字
符
串
字
典
序
越
小
3.注意还有就是i+dis[i]会大于n,大于n相当于后面补0,在前面相同的情况下越短的字符串字典序越小
3.注意还有就是i+dis[i]会大于n,大于n相当于后面补0,在前面相同的情况下越短的字符串字典序越小
#include <iostream>
#include <cstdio>
#include <stack>
#include <sstream>
#include <limits.h>
#include <vector>
#include <map>
#include <cstring>
#include <deque>
#include <cmath>
#include <iomanip>
#include <queue>
#include <algorithm>
#include <set>
#define mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define log2(a) log(a)/log(2)
#define _for(i,a,b) for( int i = (a); i < (b); ++i)
#define _rep(i,a,b) for( int i = (a); i <= (b); ++i)
#define for_(i,a,b) for( int i = (a); i >= (b); -- i)
#define rep_(i,a,b) for( int i = (a); i > (b); -- i)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define hash Hash
#define next Next
#define count Count
#define pb push_back
#define f first
#define s second
using namespace std;
const int N = 2e5+10, mod = 1e9 + 9;
const int maxn = 2e5 + 10;
const long double eps = 1e-5;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef pair<double,double> PDD;
template<typename T> void read(T &x)
{
x = 0;char ch = getchar();ll f = 1;
while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args)
{
read(first);
read(args...);
}
char a[N];
int n;
int ord[N], pos[N], dis[N];
struct SA {
int sa[maxn], ra[maxn], height[maxn];
int t1[maxn], t2[maxn], c[maxn];
void build(int *str, int n, int m) {
str[n] = 0;
n++;
int i, j, p, *x = t1, *y = t2;
for (i = 0; i < m; i++) c[i] = 0;
for (i = 0; i < n; i++) c[x[i] = str[i]]++;
for (i = 1; i < m; i++) c[i] += c[i - 1];
for (i = n - 1; i >= 0; i--) sa[--c[x[i]]] = i;
for (j = 1; j <= n; j <<= 1) {
p = 0;
for (i = n - j; i < n; i++) y[p++] = i;
for (i = 0; i < n; i++) if (sa[i] >= j) y[p++] = sa[i] - j;
for (i = 0; i < m; i++) c[i] = 0;
for (i = 0; i < n; i++) c[x[y[i]]]++;
for (i = 1; i < m; i++) c[i] += c[i - 1];
for (i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
swap(x, y);
p = 1;
x[sa[0]] = 0;
for (i = 1; i < n; i++)
x[sa[i]] = (y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + j] == y[sa[i] + j]) ? p - 1 : p++;
if (p >= n) break;
m = p;
}
n--;
for (int i = 0; i <= n; i++) ra[sa[i]] = i;
for (int i = 0, j = 0, k = 0; i <= n; i++) {
if (k) k--;
j = sa[ra[i] - 1];
while (str[i + k] == str[j + k]) k++;
height[ra[i]] = k;
}
st_init(height, n);
}
int lg[maxn], table[23][maxn];
void st_init(int *arr, int n) {
if (!lg[0]) {
lg[0] = -1;
for (int i = 1; i < maxn; i++)
lg[i] = lg[i / 2] + 1;
}
for (int i = 1; i <= n; ++i)
table[0][i] = arr[i];
for (int i = 1; i <= lg[n]; ++i)
for (int j = 1; j <= n; ++j)
if (j + (1 << i) - 1 <= n)
table[i][j] = min(table[i - 1][j], table[i - 1][j + (1 << (i - 1))]);
}
int lcp(int l, int r) {
l = ra[l], r = ra[r];
if (l > r) swap(l, r);
++l;
int t = lg[r - l + 1];
return min(table[t][l], table[t][r - (1 << t) + 1]);
}
} sa;
bool cmp(int i, int j) {
if (dis[i] != dis[j]) return dis[i] < dis[j];
if (i + dis[i] > n) return true;
if (j + dis[j] > n) return false;
int lcp = sa.lcp(i + dis[i], j + dis[j]);
return pos[i + lcp + dis[i]] < pos[j + lcp + dis[j]];
}
int main()
{
while(cin >> n >> a)
{
int pa = -1, pb = -1;
for(int i = 0; i < n; ++ i)
if(a[i] == 'a')
{
if(pa == -1) pos[i] = 0;
else pos[i] = i - pa + 1;
pa = i;
}
else
{
if(pb == -1) pos[i] = 0;
else pos[i] = i - pb + 1;
pb = i;
}
pa = pb = -1;
for(int i = n - 1; i >= 0; -- i)
if(a[i] == 'a')
{
if(pb == -1) dis[i + 1] = n - i;
else dis[i + 1] = pb - i;
pa = i;
}
else
{
if(pa == -1) dis[i + 1] = n - i;
else dis[i + 1] = pa - i;
pb = i;
}
for(int i = 1; i <= n; ++ i) ord[i] = i;
sa.build(pos,n,n+2);
sort(ord+1,ord+1+n,cmp);
for(int i = 1; i <= n; ++ i) printf("%d ",ord[i]);
puts("");
}
return 0;
}