标题:稍大的串
串可以按照字典序进行比较。例如:
abcd 小于 abdc
如果给定一个串,打乱组成它的字母,重新排列,可以得到许多不同的串,在这些不同的串中,有一个串刚好给定的串稍微大一些。科学地说:它是大于已知串的所有串中最小的串。你的任务就是求出这个“稍大的串”。
例如:
输入串:
abfxy
程序应该输出:
abfyx
再例如:
输入串:
ayyyxxff
程序应该输出:
fafxxyyy
数据规模约定:
输入的串不超过1000个字符。
特例:
如果已知的串已经是所有重组串中最大的,则原样输出读入的那个串。
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
串可以按照字典序进行比较。例如:
abcd 小于 abdc
如果给定一个串,打乱组成它的字母,重新排列,可以得到许多不同的串,在这些不同的串中,有一个串刚好给定的串稍微大一些。科学地说:它是大于已知串的所有串中最小的串。你的任务就是求出这个“稍大的串”。
例如:
输入串:
abfxy
程序应该输出:
abfyx
再例如:
输入串:
ayyyxxff
程序应该输出:
fafxxyyy
数据规模约定:
输入的串不超过1000个字符。
特例:
如果已知的串已经是所有重组串中最大的,则原样输出读入的那个串。
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
解题思路: 刚开始想的是,利用康拓展开的逆运算去解决,最后发现大数据过不了。由于我们只需要求出一个序列的下一个,就直接模拟吧!
方法一:大数据无感
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Scanner;
/**
*
* 康拓展开
*
*/
public class Main2
{
public static BigInteger[]dp = new BigInteger[1000];
public static void main(String[] args)
{
long t = System.nanoTime();
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
// 初始
init();
char c[] = str.toCharArray();
Arrays.sort(c);
if (str.equals(new StringBuffer(String.valueOf(c)).reverse().toString()))
System.out.println(str);
else
{
long result = getHash(str.toCharArray());
String s = reverHash(++result, c);
while (s.compareTo(str)<=0)
{
s = reverHash(++result, c);
}
System.out.println(s);
}
System.out.println(System.nanoTime() - t + " ns");
}
private static String reverHash(long num, char[] c)
{
boolean step[] = new boolean[c.length];
StringBuffer sb = new StringBuffer();
int j,k;
for (int i = 0; i < c.length; i++)
{
long temp = num / dp[c.length-1-i].longValue();
num -= temp * dp[c.length-1-i].longValue();
for (j=0,k=0; k <= temp; j++)
{
if (!step[j]) k++;
}
step[j-1] = true;
sb.append(c[j-1]);
}
return sb.toString();
}
private static long getHash(char[] c)
{
long sum = 0;
for (int i = 0; i < c.length; i++)
{
long count = 0;
for (int j = i+1; j < c.length; j++)
if (c[i] > c[j]) count++;
sum += count * dp[c.length-1-i].longValue();
}
return sum;
}
private static void init()
{
BigInteger b1 = new BigInteger("1");
dp[0]=dp[1]=BigInteger.ONE;
for (int i = 2; i < 1000; i++)
{
b1 = b1.multiply(BigInteger.valueOf(i));
dp[i]= new BigInteger(b1.toString());
}
}
}
方法二: 完美
import java.util.Arrays;
import java.util.Scanner;
public class Main6
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
char c1[] = str.toCharArray();
char c2[] = null;
boolean flag = false;
for (int i = c1.length-1; i > 1; i--)
{
if (c1[i] > c1[i-1])
{
char temp = c1[i];
c1[i] = c1[i-1];
c1[i-1] = temp;
c2 = new char[c1.length-i];
System.arraycopy(c1, i, c2, 0, c2.length);
Arrays.sort(c2);
flag = true;
break;
}
if (flag) break;
}
// 一般情况匹配成功
if (flag)
{
for (int i = 0; i < c1.length-c2.length; i++)
System.out.print(c1[i]);
for (int i = 0; i < c2.length; i++)
System.out.print(c2[i]);
System.out.println();
}
else
{
// 类似 19876 这样的字符串,还有 29872这样的
if (str.length() > 1 && c1[0] < c1[1])
{
int t = -1;
for (int i = str.length()-1; i>0 ; i--) if (c1[0] < c1[i]){ t = i; break;}
char temp = c1[0];
c1[0] = c1[t];
c1[t] = temp;
c2 = new char[c1.length-1];
System.arraycopy(c1, 1, c2, 0, c2.length);
Arrays.sort(c2);
for (int i = 0; i < c1.length-c2.length; i++)
System.out.print(c1[i]);
for (int i = 0; i < c2.length; i++)
System.out.print(c2[i]);
System.out.println();
}
// 特例
else
System.out.println(str);
}
}
}