SNOI 2019 字符串

SNOI 2019 字符串

题目

题解:

解法一:

记一个数组\(f\)\(f[i]=\min_j\ s[j]\neq s[j+1] (j\geq i)\),直接sort即可,复杂度\(O(nlogn)\)

#include<bits/stdc++.h>

using namespace std;

namespace Tzh{
    
    const int maxn=1000010;
    int f[maxn],rank[maxn],n; char s[maxn];
    
    bool cm(int a,int b){
        int x=a,y=b,flag=0;
        if(x>y) swap(x,y),flag=1;
        if(f[x]>=y) return 1^flag;
        else return (s[f[x]]>s[f[x]+1])^flag;
    }
    
    void work(){
        cin>>n; cin>>s+1; f[n]=n;
        for(int i=n-1;i;i--) 
            if(s[i]!=s[i+1]) f[i]=i;
            else f[i]=f[i+1];
        for(int i=1;i<=n;i++) rank[i]=i;
        sort(rank+1,rank+n+1,cm);
        for(int i=1;i<=n;i++) cout<<rank[i]<<" ";
        return ; 
    }
}

int main(){
    freopen("string.in","r",stdin);
    freopen("string.out","w",stdout);
    ios::sync_with_stdio(false);
    Tzh::work();
    return 0;
}

解法二

将字符串相同的字符先缩起来,现在字符串相邻两个字符不同.
将字符串分成若干段严格上升的子段,将每个字段的末尾成为1位置,其他成为2位置。
即对于每个1位置\(i\)都有\(s[i]>s[i+1]\),对于每个2位置\(i\)都有\(s[i]<s[i+1]\)
对于两个删1位置的串比较,前面的小
对于两个删2位置的串比较,后面的小
对于一个删1,一个删2的串,删1的小
所以先把1位置的输出,剩下的倒序输出即可
复杂度\(O(n)\)

#include<bits/stdc++.h>

using namespace std;

namespace Tzh{

    const int maxn=1000010;
    int n,top,st[maxn],last; char s[maxn];

    void work(){
        cin>>n>>s+1;
        for(int i=1;i<=n;i++){
            if(s[i]==s[i+1]&&!last) last=i;
            else if(s[i]>s[i+1]){
                if(!last) last=i;
                for(int j=last;j<=i;j++) cout<<j<<" ";
                last=0;
            }
            else if(s[i]<s[i+1]){
                if(!last) last=i;
                for(int j=i;j>=last;j--) st[++top]=j;
                last=0;
            }
        }
        for(int i=top;i;i--) cout<<st[i]<<" ";
        return ;
    }
}

int main(){
    Tzh::work();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/tang666/p/10789067.html