csu1563: Lexicography以及找出多重集的第k个串的讲解

Time Limit: 1 Sec  Memory Limit:
128 MB

Submit: 162  Solved: 52

[Submit][Status][Web
Board
]

Description

An anagram of a string is any string that can be formed using the same letters as the original. (We consider the original string an anagram of itself as well.) For example, the string ACM has the following 6 anagrams, as given in alphabetical order:

ACM

AMC

CAM

CMA

MAC

MCA

As another example, the string ICPC has the following 12 anagrams (in alphabetical order):

CCIP

CCPI

CICP

CIPC

CPCI

CPIC

ICCP

ICPC

IPCC

PCCI

PCIC

PICC

Given a string and a rank K, you are to determine the Kth such anagram according to alphabetical order.

Input

Each test case will be designated on a single line containing the original word followed by the desired rank K. Words will use uppercase letters (i.e., A through Z) and will have length at most 16. The value of K will be in the range from 1 to the number
of distinct anagrams of the given word. A line of the form "# 0" designates the end of the input.

Output

For each test, display the Kth anagram of the original string.

Sample Input

ACM 5
ICPC 12
REGION 274
# 0

Sample Output

MAC
PICC
IGNORE

HINT

The value of K could be almost 245 in the largest tests, so you should use type long in Java, or type long long in C++ to store K.

Source

如何求出一个可以有重复字符的字符集的第k大字符串呢?

为了方便描述,我们规定最小的那个串是第一个串,

首先知道这些知识,

多重集:是集合概念的推广,在一个集合中,相同的元素只能出现一次,

在多重集之中,同一个元素可以出现多次。

假设字符共有n类,个数分别为m1,m2……,mn,

那么这个多重集的全排列个数为(m1+m2+……+mn)!/m1!/m2!/……/mn!

然后呢,我们来举个例子,要知道字符集"ICPC"的第12个字符串是多少,

对第一位做出假设

C的话,那么有3!=6种串,

I的话,有3!/2!=3种串,

P的话,有3!/2!=3种串,

可知6+3+3=12,那么第一位就是P,从剩下的字符集里找出第12-6-3=3个字符串

现在字符集变成"ICC",

对第二位做出假设

C的话,那么有2!=2种串,

I的话,有2!/2!=1种串,

可知2+1=3,所以,第二位就是I,从剩下的字符集里找出第3-2=1个字符串

现在字符集变成"CC",

对第三位做出架设

C的话,那么有1!=1种串,

可知1=1,于是,第三位就是C,从剩下的字符集里找出第1-1=0个字符串,

现在字符集变成”C",

这个串并不存在,那么就是直接把剩下的那些字符,就是C补在最后就行了,

很显然,此时剩下的字符集一定都是由某个字符重复组成。

#include<map>
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<climits>
#include<list>
#include<iomanip>
#include<stack>
#include<set>
using namespace std;
typedef long long ll;
ll fac[20];
void create()
{
	fac[0]=1;
	for(ll i=1;i<=16;i++)
		fac[i]=i*fac[i-1];
}
string work(string s,ll k)
{
	map<int,int>num;
	for(int i=0;i<s.length();i++)
		num[s[i]-'A']++;
	int len=s.length();
	s.clear();
	while(num.size())
	{
		len--;
		ll sum=0;
		for(map<int,int>::iterator it=num.begin();it!=num.end();it++)
		{
			ll t=fac[len]/fac[it->second-1];

			for(map<int,int>::iterator jt=num.begin();jt!=num.end();jt++)
				if(it!=jt)
					t/=fac[jt->second];
			if(sum+t>=k)
			{
				s+=char(it->first+'A');
				it->second--;
				if(it->second==0)
					num.erase(it);
				k-=sum;
				break;
			}
			sum+=t;
		}
	}
	return s;
}
int main()
{
	create();
	string s;
	ll k;
	while(cin>>s>>k)
	{
		if(s=="#"&&k==0)
			return 0;
		cout<<work(s,k)<<endl;
	}
}
时间: 2024-10-01 14:53:03

csu1563: Lexicography以及找出多重集的第k个串的讲解的相关文章

【海量数据处理】N个数中找出最大的前K个数

N个数中找出最大的前K个数,需要用小堆实现. 分析:由于小堆的堆顶存放堆中最小的数据,可以通过与堆顶数据进行比较,将大数据存放在堆中,注意在每次改变堆顶数据后,进行调堆,使堆顶一直存放整个堆中最小元素. void AdjustDown(int *a, size_t root, size_t size)//下调 {//小堆 size_t parent = root; size_t child = parent * 2 + 1; while (child < size) { if (child + 

在字符串中找出连续最长的数字串 在字符串中找出连续最长的数字串,并把这个串的长度返回

写一个函数,它的原形是int continumax(char *outputstr,char *intputstr)功能:在字符串中找出连续最长的数字串,并把这个串的长度返回,并把这个最长数字串付给其中一个函数参数outputstr所指内存.例如:"abcd12345ed125ss123456789"的首地址传给intputstr后,函数将返回9, #include<iostream> using namespace std; int ContinueMax(char *

[华为机试练习题]43.在字符串中找出连续最长的数字串

题目 描述: 请一个在字符串中找出连续最长的数字串,并把这个串的长度返回:如果存在长度相同的连续数字串,返回最后一个连续数字串: 注意:数字串只需要是数字组成的就可以,并不要求顺序,比如数字串"1234"的长度就小于数字串"1359055",如果没有数字,则返回空字符串("")而不是NULL! 样例输入 abcd12345ed125ss123058789 abcd12345ss54761 样例输出 输出123058789,函数返回值9 输出547

剑指Offer(Java版)第六十五题:给定一棵二叉搜索树,请找出其中的第k小的结点。 例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。

/*给定一棵二叉搜索树,请找出其中的第k小的结点.例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4.*//*二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值*///思路:从最左边的叶子节点开始找起. import java.util.*; public clas

找出整数中第k大的数

一  问题描述: 找出m个整数中第k(0<k<m+1)大的整数. 二  举例: 假设有12个整数:data[1, 4, -1, -4, 9, 8, 0, 3, -8, 11, 2, -9],请找出第5大的数(容易知道是0). 三   算法思路:        一种基于快排思想的算法可以在O(n)复杂度内找到第k大的数,首先要知道partition这个函数,它可以调整一个序列 使小于key的元素都排在key左边,大于key的元素都排在key右边,key可以在这个序列中任意选择,一般选择给定序 列

算法题之找出数组里第K大的数

问题:找出一个数组里面前K个最大数. 解法一(直接解法): 对数组用快速排序,然后直接挑出第k大的数.这种方法的时间复杂度是O(Nlog(N)).N为原数组长度. 这个解法含有很多冗余,因为把整个数组都排序了,而实际上我们不需要这样做. 解法二(K数组排序): 首先,创建一个长度为K的空数组.从原数组中先挑出K个数进行排序并放到这个空数组中.这一步的时间复杂度是O(Klog(K)). 接着,从剩下的N-K个值中,依次遍历并与上面数组的末尾的数(即里面的最大数)相比较,并插入到合适位置.这一步的时

215. Kth Largest Element in an Array找出数组中第k大的值

堆排序做的,没有全部排序,找到第k个就结束 public int findKthLargest(int[] nums, int k) { int num = 0; if (nums.length <= 1) return nums[0]; int heapSize = nums.length; //1.构建最大堆 int half = (heapSize-2)/2; for (int i = half;i >= 0;i--) { adjust(nums,heapSize,i); } while

字符串中找出连续最长的数字串(正则表达式)

题目描述 读入一个字符串str,输出字符串str中的连续最长的数字串 输入描述: 个测试输入包含1个测试用例,一个字符串str,长度不超过255. 输出描述: 在一行内输出str中里连续最长的数字串. 示例1 输入 abcd12345ed125ss123456789 输出 123456789 1 /** 2 * 3 * 4 用正则表达式 替换 非数字 字符 在用 split 分割 得到 字符串数组 5 * @author Dell 6 * 7 */ 8 import java.util.Scan

最长(大)回文串的查找(字符串中找出最长的回文串)PHP实现

首先还是先解释一下什么是回文串:就是从左到右或者从右到左读,都是同样的字符串.比如:上海自来水来自海上,bob等等. 那么什么又是找出最长回文串呢? 例如:字符串abcdefedcfggggggfc,其中efe,defed,cdefedc,gg,ggg,gggg,ggggg,gggggg,fggggggf,cfggggggfc都是回文串,左右完全一样. 这其中,有最短的gg,最长的cfggggggfc,还有其他长度的.忽略长度为1的.毕竟一个字符的都算回文了. 那么,找出最长的,就是找出这个cf