P1124 文件压缩

87 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 8 天,点击查看活动详情

题目:该算法具体如下:对一个长度为 n 的字符串 S,首先根据它构造 n 个字符串,其中第 i 个字符串由将 S 的前 i−1 个字符置于末尾得到。然后把这 n 个字符串按照首字符从小到大排序,如果两个字符串的首字符相等,则按照它们在 S 中的位置从小到大排序。排序后的字符串的尾字符可以组成一个新的字符串 ′S′ ,它的长度也是 n,并且包含了 S 中的每一个字符。最后输出 ′S′ 以及 S 的首字符在 ′S′ 中的位置 p。
思路:假设给出的串是a串,对a串排序之后的是b串,那么b串其实就是题目中排好序的首字母,a串就是尾字母,那么就可以根据第一个位置来找出原串s中的最后一个位置,然后再根据最后一个位置找到倒数第二个,依次递推下去就可以找出原串

#include<bits/stdc++.h>
//#pragma-GCC-optimize("-Ofast");
#define ll long long
#define int long long
#define lowbit(x) ((x)&(-x))
#define endl '\n'
using namespace std;
const ll mod=998244353;
const ll inf=1e9;
const double pi=acos(-1);
const int N=1e6+100;
ll qpow(ll a,ll b)
{
    ll res=1;
    while(b)
    {
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
ll getinv(ll a){return qpow(a,mod-2);}
int n,p;
char s[100005],s1[100005],ans[100005];
signed main()
{
    //ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>n>>(s+1)>>p;
    memcpy(s1,s,sizeof(s));
    sort(s1+1,s1+n+1);
    //题目中说的是从小到大且按照出现的顺序排序,所以第一个和s[p]相等的一定是第一个字母,
    那么他后面一定是最后一个字母
    for(int i=1;i<=n;i++)if(s1[i]==s[p]){p=i;break;}
    int cnt=n+1;
    while(cnt>1){
        ans[--cnt]=s[p];
        s1[p]='#';
       //因为要倒着找,所以要逆序遍历,道理和上面一样
        for(int i=n;i>=1;i--)if(s1[i]==s[p]){p=i;break;}
    }
    for(int i=1;i<=n;i++) cout<<ans[i];
    return 0;
}
```
```