子序列翻转 51Nod - 1335

https://www.51nod.com/Challenge/Problem.html#!#problemId=1335

和字典序有关的题 要么是字符串题 要么就是DP或者贪心乱搞

找一个最小的i作为x 满足a[i]>min(a[j]) i+1<=j<=n-1 因为字典序和二进制串一样 都是高位决定一切

然找出所有k 满足a[k]==min(a[j]) i+1<=j,k<=n-1 一位一位比出个字典序最小或者y最小的即可

最后注意向两边拓展一下xy

#include  <bits/stdc++.h>
using namespace std;
#define pb push_back
const int maxn=3e3+10;

vector <int> pre;
int ptr[maxn],book[maxn];
int n;
char ch[maxn];

int main()
{
    int t,i,j,x,y;
    char minn;
    scanf("%d",&t);
    while(t--){
        scanf("%s",ch);
        n=strlen(ch),x=3000,y=3000;
        for(i=0;i<n;i++){
            minn='z'+1;
            for(j=i+1;j<n;j++){
                minn=min(minn,ch[j]);
            }
            if(minn>=ch[i]) continue;
            pre.clear();
            for(j=i+1;j<n;j++){
                if(ch[j]==minn) pre.pb(j);
            }
            if(pre.size()>0){
                x=i;
                break;
            }
        }
        for(i=0;i<pre.size();i++){
            ptr[i]=pre[i],book[i]=0;
        }
        for(i=0;i<n-x;i++){
            minn='z'+1;
            for(j=0;j<pre.size();j++){
                if(book[j]) continue;
                minn=min(minn,ch[ptr[j]]);
            }
            for(j=0;j<pre.size();j++){
                if(book[j]) continue;
                if(ch[ptr[j]]!=minn) book[j]=1;
            }
            for(j=0;j<pre.size();j++){
                if(ptr[j]<=pre[j]){
                    ptr[j]--;
                    if(ptr[j]<x) ptr[j]=pre[j]+1;
                }
                else ptr[j]++;
            }
        }
        for(i=0;i<pre.size();i++){
            if(!book[i]) y=min(y,pre[i]);
        }
        if(x==3000) printf("0 0\n");
        else{
            while(0<=x-1&&y+1<n&&ch[x-1]==ch[y+1]) x--,y++;
            printf("%d %d\n",x,y);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/84972749