POJ 1146 ID Codes 用字典序思想生成下一个排列组合

ID Codes
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 7644   Accepted: 4509

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 of `b' 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

题意:

首先会给定一个字符串,因为开发商要通过交换字母位置生成新的字符串来节约刻印这些字符串的成本,假设现在已经按字典序将所有可能的排列全部找出来了,问你当前给定的这个字符串的下一个排列(按照字典序)是什么?例如假定一个识别码有三个a,两个b,一个c,在满足条件的60个编码中按字典序选出三个是:abaabc,abaacb,ababac,现在题目给定的字符串是abaacb,那么按字典序来讲,下个字符串是ababac,输出"ababac"即可。

分析:

本题利用的是字典序思想来对字符串进行改造,也就是在不改变字母组成的情况下生成该字符串的下一个字典序排列(没有的话输出“No Successor”)。

解法:

1.从后往前先找出一个正序。(找不到的话就是No Successor)。

2.(记这个正序的下标分别是id-1,id)从找出的的那个正序的下标(id)开始往后遍历,找到最后一个小于s[id-1]的那个元素(记下标为 j)。

3.swap(s[id-1],s[j]);交换这两个数来破坏原来的正序,又因为新找到的元素字典序小于s[id-1]所以交换以后的字典序一定更小。

4.sort(s+id,s+len);对从id到末尾的所有元素从小到大排序来保证我们新得出的这个字符串按字典序排序的结果是紧邻在原串之后的。

AC code:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char s[55];
int solve()
{
    int len=strlen(s);
    int id=len-1;
    while(id>=0)
    {
        if(s[id]>s[id-1])    break;
        else
        {
            id--;
        }
    }
    if(id==0)    return 0;
    int mpre=id-1,mnow=id;
    for(int j=mnow+1;j<len;j++)
    {
        if(s[j]<=s[mpre])    continue;
        if(s[j]<s[mnow])    mnow=j;
    }
    swap(s[mnow],s[mpre]);
    sort(s+id,s+len);
    return 1;
}
int main()
{
    //freopen("input.txt","r",stdin);
    while(~scanf("%s",s)&&s[0]!='#')
    {
        if(solve())    printf("%s\n",s);
        else printf("No Successor\n");
    }
}
View Code

猜你喜欢

转载自www.cnblogs.com/cautx/p/11403927.html