LOJ 3095 [SNOI 2019]字符串

https://www.cnblogs.com/cjc030205/p/11638110.html

附上大佬的博客转一下:

题面描述:

给出一个长度为  的由小写字母组成的字符串 ,设其中第  个字符为 

设删掉第  个字符之后得到的字符串为 ,请按照字典序对  从小到大排序。若两个字符串相等,则认为编号小的字符串字典序更小。

输入格式

第一行一个整数 

第二行一个长为  的由小写字母组成的字符串 

输出格式

输出一行  个整数 ,用空格隔开。表示 

样例

样例输入 1

7
aabaaab

样例输出 1

3 7 4 5 6 1 2

hhh作为一道签到题还挺温暖人心的但是怎么就有憨憨同学上来就搞个后缀数据结构

ii与串jj比较,明显只关心[i,j][i,j],具体来说,是[i+1,j][i+1,j]和[i,j1][i,j−1]

考虑串ii和串j(j=i+1)j(j=i+1)比较,ii之后的串一定会保留第ii位,

如果SiSjSi≥Sj,因为第ii位≥第jj位,所以SiSi一定会比后面的小

同理,如果第ii位<<第jj位,所以SiSi一定会比后面的串大

hhh所以永远比后面的小和永远比后面的大可以直接扔掉了,然后因为只用考虑相邻位,就直接O(1)O(1)check就好了

相等的时候直接拉起来判后面的,前面的直接按照顺序排就好。

复杂度O(n)

#include<cstdio>
#include<cstring>
const int N = 2e6+7;
typedef long long LL;
char S[N];
int rank[N], n;
int main() {
  scanf("%d", &n);
  scanf("%s", S + 1);
  int l = 1, r = n;
  for ( int i = 2, j = 1; i <= n; i++) {
    while (S[i] == S[j] && i < n) i++;
    if (S[j] >= S[i]) while (j < i) rank[l++] = j++;
    else {
      for ( int k = i - 1; k >= j; k--) rank[r--] = k;
      j = i;
    }
  }
  if (l == r) rank[l] = n;
  for (R int i = 1; i <= n; i++)
    printf("%d ", rank[i]);
} 

猜你喜欢

转载自www.cnblogs.com/flyljz/p/11722357.html