版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/monochrome00/article/details/84533537
题目链接<https://cn.vjudge.net/problem/1595745/origin>
题意:
给出一段01串,要求把其中一段的子串替换成一个1,使得新得到的串字典序最大。输出要替换的子串。
题解:
贪心的想,最开始的几个连续的1不要碰,后面找一个字典序最大的后缀也保留,把中间的串替换掉。这样直接套一个后缀数组就能过了。
比赛的时候我没用后缀数组,自己想了一个算法也过了。还没被证伪,先写下来记下。
i记录当前字典序最大的后缀下标,j记录可能是更大字典序的下标。另外开一个pi,pj表示i和j往后延展比较。
- 如果s[pi]>s[pj],也就是说i代表的后缀仍旧比j大,那么i不变,j跳到pj的位置上。
- 如果s[pi]<s[pj],也就是说i代表的后缀比j小,那么i跳到j的位置上。j跳到pj前面第一次出现1的位置。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+7;
const int inf=1e9;
char s[N];
int main()
{
int n;
scanf("%d",&n);
scanf("%s",s+1);
int ss;
for(ss=1;ss<=n;ss++){
if(s[ss]=='0') break;
}
if(ss>n){printf("0 0\n");return 0;}
printf("%d ",ss-1);
int i=ss,j=ss;
while(i<=n&&j<=n){
if((s[j]<s[i])||(i==j)){j++;continue;}
if(s[j]>s[i]){i=j;continue;}
int pi=i+1,pj=j+1;
while(pi<=n&&pj<=n){
if(s[pi]==s[pj]){pi++;pj++;continue;}
if(s[pi]>s[pj]) break;
i=j;
while(s[pj-1]=='1') pj--;
break;
}
j=pj;
}
printf("%d\n",i-ss);
}