51nod 1335 子序列翻转

来源:互联网 发布:淘宝店铺无线端装修 编辑:程序博客网 时间:2024/06/15 00:17

1335 子序列翻转
题目来源: TopCoder
基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
 收藏
 关注
初始有一个字符串s,串的长度L不超过2500。你可以对串中一个子串进行一次翻转,确切的说,你可以选择一对整数
{ x,y } 其中0<=x<=y<L,然后翻转字符串中索引在x到y区间上的子串,将该串从s[x]s[x+1]...s[y]变为s[y]...s[x+1]s[x]。例如, s = "abcdefg",{ x,y } 取 { 2,5 } 那么翻转后是 "abfedcg",如果取 { 0,1 } 结果是 "bacdefg",如果取 { 3,3 } 那结果是 "abcdefg"(即没变)。你的目的是翻转一次后,使字符串的字典序尽可能的小,那么问最优的 { x,y } 是多少?如果存在多组解能使s变化后字典序最小,那么输出其中x最小的那组解,如果还有多组解,那么输出y最小的解。


Input
多组测试数据,第一行一个整数T,表示测试数据数量,1<=T<=5之后有T组结构相同的数据:每组包含一行一个字符串s,其中s的长度L满足1<=L<=2500且s只包含小写字母'a'~'z'
Output
一组数据输出一行两个整数,即最优的翻转子序列的区间索引x,y
Input示例
2abdcaabbcc
Output示例
2 30 0

https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1335


这个题要智商的,先开始枚举x,y  直接爆炸。

后来看到题解一句话。x是确定的。后来思考一下字典序。

发现x就是确定的。要让第一个大的开头变小。哪怕变小一点点也比后面的优越。

然后就是 。找到第一x,枚举y。

复杂度n^2  

主要复杂度用在了交换上面。


= = 然后发现是水题


代码要短= =

#include <bits/stdc++.h>using namespace std;string run(string s,int x,int y){    for(int i=x;i<=(x+y)/2;i++)        swap(s[i],s[y-i+x]);    return s;}int main(){    int t;    cin>>t;    while(t--)    {        string s,b,c;        cin>>s;        int x=0,y=0;        b=s;        sort(&b[0],&b[0]+b.size());//找到x,这样比较快        for(int i=0;s[i];i++)//对比。            if(s[i]>b[i])            {                x=y=i;                break;            }        b=s;        for(int j=x+1;s[j];j++)            if(s[j]<=s[x])            {                c=run(s,x,j);                if(c<b)                {                    b=c;                    y=j;                }            }        cout<<x<<' '<<y<<endl;    }    return 0;}










原创粉丝点击