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;
}
posted @ 2019-04-29 10:48  Jack_the_Ripper  阅读(185)  评论(1编辑  收藏  举报