POJ 1146:ID Codes

ID Codes

Time Limit: 1000MS Memory Limit: 10000K

Total Submissions: 6281 Accepted: 3769

Description

It is 2084 and the year of Big Brother has finally arrived, albeit a century late. In order to exercise greater control over its citizens and thereby to counter a chronic breakdown in law and order, the Government decides on a radical measure–all citizens are to have a tiny microcomputer surgically implanted in their left wrists. This computer will contains all sorts of personal information as well as a transmitter which will allow people’s movements to be logged and monitored by a central computer. (A desirable side effect of this process is that it will shorten the dole queue for plastic surgeons.)

An essential component of each computer will be a unique identification code, consisting of up to 50 characters drawn from the 26 lower case letters. The set of characters for any given code is chosen somewhat haphazardly. The complicated way in which the code is imprinted into the chip makes it much easier for the manufacturer to produce codes which are rearrangements of other codes than to produce new codes with a different selection of letters. Thus, once a set of letters has been chosen all possible codes derivable from it are used before changing the set.

For example, suppose it is decided that a code will contain exactly 3 occurrences of a‘, 2 ofb’ and 1 of `c’, then three of the allowable 60 codes under these conditions are:

  abaabc

  abaacb

  ababac

These three codes are listed from top to bottom in alphabetic order. Among all codes generated with this set of characters, these codes appear consecutively in this order.

Write a program to assist in the issuing of these identification codes. Your program will accept a sequence of no more than 50 lower case letters (which may contain repeated characters) and print the successor code if one exists or the message `No Successor’ if the given code is the last in the sequence for that set of characters.

Input

Input will consist of a series of lines each containing a string representing a code. The entire file will be terminated by a line consisting of a single #.

Output

Output will consist of one line for each code read containing the successor code or the words ‘No Successor’.

Sample Input

abaacb

cbbaa

#

Sample Output

ababac

No Successor

这道题是要输出给定字符串的字典顺序的下一个,如果没有下一个,则输出No Successor。

字典序如下:

设P是1~n的一个全排列:p=p1p2……pn=p1p2……pj-1pjpj+1……pk-1pkpk+1……pn

1)从排列的右端开始,找出第一个比右边数字小的数字的序号j(j从左端开始计算),即 j=max { i | pi < pi+ 1}

2)在pj的右边的数字中,找出所有比pj大的数中最小的数字pk,即 k=max{i|pi>pj}(右边的数从右至左是递增的,因此k是所有大于pj的数字中序号最大者)

3)对换pj,pk

4)再将pj+1……pk-1pkpk+1……pn倒转得到排列p’=p1p2…..pj-1pjpn…..pk+1pkpk-1…..pj+1,这就是排列p的下一个排列。

上面这一段话摘自百度百科,之前的理解只是知道比方说 123

字典顺序就是

1 2 3

1 3 2

2 1 3

2 3 1

3 1 2

3 2 1

但根据上面的方法其实就可以写出求下一个字典顺序的字符串了。12345是起始,54321是终止。

比方说:13254

想找下一个字典顺序,找符合大小关系的。

发现5>4,pass。

2<5,perfect。

就是2了,从2这里入手。之后只需要在后面的5 4 中找一个比2大的最小的数,对换。此时序列变为1 3 4 5 2。

再然后,对4后面的序列,进行正常从小到大排列,就是要找的下一个字典排序。

1 3 4 2 5。

所以,可以直接根据这个思想,写出代码

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;

int front,behind;
string a;

bool find()
{
    int len =a.length()-1;
    while(len>0)
    {
        if(a[len-1] >= a[len])
        {
        }
        else
        {
            front = len-1;
            return true;
        }
        len--;
    }
    return false;
}

void change()
{
    int len =a.length()-1;
    int min=200;

    while(len>front)
    {
        if(a[len]>a[front]&&(int)a[len]<min)
        {
            min=len;
        }
        len--;
    }
    char temp=a[min];
    a[min]=a[front];
    a[front]=temp;
}

void sort()
{
    int len = a.length();
    int i,j;
    char temp;

    for(i=front+1;i<len;i++)
    {
        for(j=i;j<len;j++)
        {
            if(a[i]>a[j])
            {
                temp=a[i];
                a[i]=a[j];
                a[j]=temp;
            }
        }
    }
}

int main()
{
    while(cin>>a&&a!="#")
    {
        if(find())
        {
            change();
            sort();
            cout<<a<<endl;
        }
        else
        {
            cout<<"No Successor"<<endl;
        }
    }
    return 0;
}

当然这个题,在algorithm.h文件中,有直接可以使用的字典顺序的函数next_permutation(),具体代码如下

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
    string a;
    while(cin>>a&&a!="#")
    {
        if(next_permutation(a.begin(),a.end()))
        {
            cout<<a<<endl;
        }
        else
        {
            cout<<"No Successor"<<endl;
        }
    }
    return 0;
}

这里面的next_permutation()函数就是求其下一个字典顺序,和prev_permutation()函数相对应,使用用法有一些像sort函数,可以对int数组 ,char数组,string类型进行字典顺序查找,也可以在第三个参数加上cmp函数,自己自定义的一个排序函数。具体用法可以参考POJ 1256这道题,体现的比较明显。

时间: 2024-07-28 17:40:43

POJ 1146:ID Codes的相关文章

1146 ID Codes

题目链接: http://poj.org/problem?id=1146 题意: 给定一个字符串(长度不超过50), 求这个字符串的下一个字典序的字符串, 如果已经是最大字典序, 那么输出 "No successor". 分析: <algorithm>中有一个现成的next_permutation(begin, end), 对输入的字符串进行排列. 原型如下: 1 template<class BidirectionalIterator> 2 bool next

POJ 3318:Matrix Multiplication(随机算法)

http://poj.org/problem?id=3318 题意:问A和B两个矩阵相乘能否等于C. 思路:题目明确说出(n^3)的算法不能过,但是通过各种常数优化还是能过的. 这里的随机算法指的是随机枚举矩阵C的一个位置,然后通过A*B计算是否能够得到矩阵C相应位置的数,如果不等,就直接退出了,如果跑过一定的数量后能够相等,那么就可以判断这个矩阵C等于A*B的.第一次见这样的题目...有点新奇. 暴力算法: 1 #include <cstdio> 2 using namespace std;

POJ 1986:Distance Queries(倍增求LCA)

http://poj.org/problem?id=1986 题意:给出一棵n个点m条边的树,还有q个询问,求树上两点的距离. 思路:这次学了一下倍增算法求LCA.模板. dp[i][j]代表第i个点的第2^j个祖先是哪个点,dp[i][0] = i的第一个祖先 = fa[i].转移方程:dp[i][j] = dp[dp[i][j-1][j-1]. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm&g

POJ 3368:Frequent values RMQ

Frequent values 题目链接: http://poj.org/problem?id=3368 题意: 给出一个非递减序列,求区间内最多的数字的数量 题解: 水题,dp[i][j]记录从 i 开始2^j个数中的出现最多的数,合并dp[i][j]和dp[i+(1<<j)][j]得到dp[i][1<<(j+1)]的时候,由于序列是连续的,只要多考虑一个i+(1<<j)-1(即dp[i][j]所能到达的最右端)上得数字在区间内出现的次数就好了. 代码 #includ

POJ 2955:Brackets(区间DP)

http://poj.org/problem?id=2955 题意:给出一串字符,求括号匹配的数最多是多少. 思路:区间DP. 对于每个枚举的区间边界,如果两边可以配对成括号,那么dp[i][j] = dp[i+1][j-1] + 2,表示由上一个状态加上当前的贡献. 然后和普通的区间合并一样去更新. 1 #include <cstring> 2 #include <cstdio> 3 #include <iostream> 4 #include <string&

POJ 3264:Balanced Lineup(RMQ模板题)

http://poj.org/problem?id=3264 题意:给出n个数,还有q个询问,询问[l,r]区间里面最大值和最小值的差值. 思路:RMQ模板题,开两个数组维护最大值和最小值就行. 1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 #define N 50010 7 #define

POJ 2104:K-th Number(整体二分)

http://poj.org/problem?id=2104 题意:给出n个数和m个询问求区间第K小. 思路:以前用主席树做过,这次学整体二分来做.整体二分在yr大佬的指点下,终于大概懂了点了.对于二分能够解决的询问,如果有多个,那么如果支持离线处理的话,那么就可以使用整体二分了. 在这题二分可行的答案,根据这个答案,把询问操作丢在左右两个队列里面分别递归继续按这样处理.注释里写的很详细. 1 #include <iostream> 2 #include <cstdlib> 3 #

POJ 2195:Going Home(最小费用最大流)

http://poj.org/problem?id=2195 题意:有一个地图里面有N个人和N个家,每走一格的花费是1,问让这N个人分别到这N个家的最小花费是多少. 思路:通过这个题目学了最小费用最大流.最小费用最大流是保证在流量最大的情况下,使得费用最小. 建图是把S->人->家->T这些边弄上形成一个网络,边的容量是1(因为一个人只能和一个家匹配),边的费用是曼哈顿距离,反向边的费用是-cost. 算法的思想大概是通过SPFA找增广路径,并且找的时候费用是可以松弛的.当找到这样一条增

POJ 2679:Adventurous Driving(SPFA+DFS)

http://poj.org/problem?id=2679 Adventurous Driving Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1596   Accepted: 455 Description After a period of intensive development of the transportation infrastructure, the government of Ruritania