求字典序最大的子串 | ||||||
| ||||||
Description | ||||||
给定一串仅包含小写字母的字符串,找出字典序最大的子串。
对于字符串s, x和y是它的子串,x比y大,说明用C语言的字符串比较函数 strcmp(x, y) > 0。
如 s="ababba", x = "bbba", y="abaa" , x和y都是s的子串,x比y大。
| ||||||
Input | ||||||
有多组测试数据,每组测试一行,仅包含一个由小写字母组成的字符串,长度小于等于10^6。 | ||||||
Output | ||||||
对于每组测试数据,输出一行,为字典序最大的子串。 | ||||||
Sample Input | ||||||
ababba abbcbccacbbcbaaba | ||||||
Sample Output | ||||||
bbba cccccbba | ||||||
Source | ||||||
CodeForces Div124-1 |
在求字典序最大的子串之前,我们需要了解一下比较字典序的strcmp函数的比较原理:
首先两个字符串比较字典序先比较第一个字母,如果第一个字母不同则按照a-z的顺序比较字典序,排序靠前的字典序更小。如果第一个字母相同递推到比较第二个字母,一直递推下去,直到遇到两个不同的字母或者是一方的长度已经遍历完毕,那么另一方的长度如果大于它,那么长度小的字典序更小。
贪心思路:
1、对于这个题目我们要求字典序最大的子串,那么我们就应该让子串的第一个字母最大。
2、让这个子串形成一个最长递减子序列【包括等于】。这里我们逆向实现。
逆向实现的思路:从主串的最后一个字母出发,向前遍历,如果前边的字母大于等于后边串中最大的字母,那么保存下来,最后逆序输出即可。
AC代码:
#include<stdio.h>
#include<string.h>
#include<cstring>
#include<iostream>
using namespace std;
char a[1000005];
int vis[1000005];
char ans[1000005];
int main()
{
while(~scanf("%s",a))
{
int lena=strlen(a);
memset(vis,0,sizeof(vis));
int maxn=-0x3f3f3f3f;
int pos;
for(int i=0;i<lena;i++)
{
vis[i]=a[i]-'0';
if(vis[i]>maxn)
{
maxn=vis[i];
pos=i;
}
}
int cont=0;
int maxn2=-0x3f3f3f3f;
for(int i=lena-1;i>=pos;i--)
{
if(vis[i]>=maxn2)
{
ans[cont]=a[i];
cont++;
maxn2=vis[i];
}
}
ans[cont]='\0';
for(int i=cont-1;i>=0;i--)
{
printf("%c",ans[i]);
}
printf("\n");
}
}