【题面】
【思路分析】
不知道大家在刚学字符串的时候有没有见过这样一道题 题意:
给你一个字符串
去掉一个字符
使所得字符串字典序最小
输出这个字典序最小的结果
因为越前面的字符越重要 所以这道题的求解过程就是从前往后扫找到第一个st[i]>st[i+1] 这样的话所得字符串的第i位就比原字符串要小了,并且因为i最小所以是字典序最小
input:
abcdefgabcde
output:
abcdefabcde
去掉第i个字符(st[i]>st[i+1])所得串必然字典序小于原串
i越小,字典序越小
——————
相似的问题是去掉一个字符使字典序最大 所以这道题的求解过程就是从前往后扫找到第一个st[i]<st[i+1] 这样的话所得字符串的第i位就比原字符串要大了
input:
abcdefgabcde
output:
acdefgabcde
去掉第i个字符(st[i]<st[i+1])所得串必然字典序大于原串
i越小,字典序越大
——————
本题就跟这两道题相似 我们先把字符相同的连续子串合并一下 然后按上面的流程分为大于原串和小于原串
大于原串赋值为1 小于原串赋值为-1
然后以与原串的关系为第一关键字
所在位置为第二关键字排序 (同为-1 越前越小 同为1 越后越小)
然后直接输出即可
【代码】
如果还不能理解可以看一下我的代码:
#include<bits/stdc++.h>
using namespace std;
struct AA{
int begin_,end_,leixing_;
char ccc;
} a[1000005];
char c[1000005];
bool cmp(AA x,AA y)
{
if (x.leixing_!=y.leixing_) return x.leixing_<y.leixing_;
if (x.leixing_==-1)
return x.begin_<y.begin_;
else
return x.begin_>y.begin_;
}
int main()
{
int n;
scanf("%d\n",&n);
for (int i=1;i<=n;i++)
c[i]=getchar();
a[1].begin_=a[1].end_=1;
a[1].ccc=c[1];
int num=1;
for (int i=2;i<=n;i++)
if (c[i]==c[i-1])
a[num].end_++;
else
{
num++;
a[num].begin_=a[num].end_=i;
a[num].ccc=c[i];
}
for (int i=1;i<num;i++)
if (a[i].ccc<a[i+1].ccc)
a[i].leixing_=1;
else
a[i].leixing_=-1;
sort(a+1,a+num+1,cmp);
for (int i=1;i<=num;i++)
{
for (int j=a[i].begin_;j<a[i].end_;j++)
printf("%d ",j);
printf("%d",a[i].end_);
if (i==num)
puts("");
else
putchar(' ');
}
return 0;
}