[洛谷P5329][SNOI2019]字符串

题目大意:给一个长度为$n$的字符串$s$,字符串$p_i$为字符串$s$去掉第$i$个字符后形成的字符串。请给所有字符串$p_i$排序(相同字符串按编号排序)

题解:先去掉所有连续相同字符,因为它们形成的字符串一定相同(也就是说只按编号排序)。然后发现对于两个字符串$p_i,p_j(i<j)$只需要比较$s_i$与$s_{i+1}$的大小就可以比较这两个字符串的大小。即$p_i$只会排在$p_{i+1}\sim p_n$的前面或后面。所以可以用链表解决

卡点:

 

C++ Code:

#include <iostream>
#include <cstdio>
#include <algorithm>
#define maxn 1000010

int n, m;
int pos[maxn], len[maxn], nxt[maxn];
char s[maxn], p[maxn];
int main() {
    std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
    std::cin >> n >> (s + 1);
    for (int i = 1, j = i; i <= n; i = j) {
        while (j <= n && s[i] == s[j]) ++j;
        p[++m] = s[i], pos[m] = i, len[m] = j - i;
    }
    int L, R; L = R = m;
    for (int i = m - 1; i; --i)
        if (p[i] > p[i + 1]) nxt[i] = L, L = i;
        else nxt[R] = i, R = i;
    for (int i = L; i; i = nxt[i])
        for (int j = 0; j < len[i]; ++j) std::cout << pos[i] + j << ' ';
    return 0;
}

 

转载于:https://www.cnblogs.com/Memory-of-winter/p/11121961.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值