全排列

数据结构——康托展开

♀尐吖头ヾ 提交于 2019-11-29 15:43:25
含义   康托展开是一个 全排列 到一个 自然数 的 双射 ,常用于构建 哈希表 时的空间压缩。 康托展开的实质是计算当前排列在所有由小到大全排列中的顺序,因此是 可逆 的。 原理   X = s 1 (n-1)! + s 2 (n-2)! + s 3 (n-3)! + …… + s n-1 * 1! + s n * 0!   其中s i 表示在第i位右边比a i 小的数的个数。   我们现在用s l 表示第i位左边比a i 小的数的个数,s r 表示第i位右边比a i 小的数的个数,显然可以得到如下等式:   a i = s l + s r + 1   故公式中的si可以用上述等式计算:s r = a i - s l -1   依照上述原理,则{1,2,3,4,5}的一种全排列{3,4,1,5,2}可以映射为{2,2,0,1,0}   根据公式,该集合实际上表示的就是一个变进制数。   简便计算:X = ((s 1 * (n-1) + s 2 ) * (n-3) + s 3 ) * (n-3) + …… 康托展开   暴力 O(n 2 ):   为了便于讲解下面的线段树优化,此处选择维护vis数组的方式(当然直接比大小也是一样的)。   vis[j]用以记录j是否已出现,未出现为0,已出现为1。故a[i]左边比其小的数的个数就是vis[j]的和(j<a[i])。   计算ans时

字符串的排列

随声附和 提交于 2019-11-29 12:24:55
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串 abc,则打印出由字符 a, b, c 所能排列出来的所有字符串 abc, acb, bac, bca, cab 和 cba。 一般思路: 正常人的思维是, 固定第一个字符 ,然后依次将后面的字符串与前面的交换,那么排列的个数就是除了第一个字符以外,其他字符的排列个数+1。 也就是固定一个字符串之后,之后再将问题变小,只需求出后面子串的排列个数就可以得出结果,当然第一时间想到的就是递归的算法了。 下面这张图很清楚的给出了递归的过程: 固定第一个位置,调换后面的位置。 很明显, 递归的出口,就是只剩一个字符的时候 ,递归的循环过程,就是从每个子串的第二个字符开始依次与第一个字符交换,然后继续处理子串。 还有一个问题要注意,就是如果字符串中有重复的字符串。 由于全排列就是从第一个数字起,每个数分别与它后面的数字交换,我们先尝试加个这样的判断——如果一个数与后面的数字相同那么这两个数就不交换 了。例如 abb,第一个数与后面两个数交换得 bab,bba。然后 abb 中第二个数和第三个数相同,就不用交换了。但是对 bab,第二个数和第三个数不同,则需要交换,得到 bba。由于这里的bba和开始第一个数与第三个数交换的结果相同了,因此这个方法不行。 换种思维,对abb,第一个数a与第二个数b交换得到bab

8.11 hdu 多校第五场补题

◇◆丶佛笑我妖孽 提交于 2019-11-27 00:28:41
6629 string matching 题意:给定一个字符串s,求s与自身所有前缀暴力匹配所需匹配次数 分析:每个前缀匹配次数即自身长度,exkmp的next数组记录的就是与自身最大匹配前缀的长度,加一遍就行,注意边界 代码: #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<string> #include<vector> #define fi first #define se second #define rep( i ,x ,y ) for( int i= x; i<= y ;i++ ) #define reb( i ,y ,x ) for( int i= y; i>= x ;i-- ) #define mem( a ,x ) memset( a ,x ,sizeof(a)) using namespace std; typedef long long ll; typedef pair<int ,int> pii; typedef pair<ll ,ll> pll; typedef pair<string ,int> psi; char s[1005000]; int nxt[1005000]; void getnext( int l){ int a=0 ,p

问题 A 分治法求解全排列问题

做~自己de王妃 提交于 2019-11-26 12:10:47
题目描述 设R=(1, 2, .., n),计算R的全排列。 分治法求解全排列的算法思想: 设R=(1, 2, .., n)的全排列为P(R), 若R=(),则P()=(); 否则,P(R)={(1)P(2, 3, .., n),(2)P(1, 3, .., n), (3)P(2, 1, .., n), .., (n)P(2, .., n-1, 1)}; 同样地,P(2, 3, .., n)={(2){3, 4, .., n}, (3){2, 4, .., n}, .., (n){3, .., n-1, 2}} 输入 输入为一组不大于7的整数。 输出 对每个输入的整数n,用分治法计算并输出1..n的全排列。 样例输入 123 样例输出 1 1 2 2 1 1 2 3 1 3 2 2 1 3 2 3 1 3 2 1 3 1 2 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<malloc.h> using namespace std; void perm(int a[],int k,int m){ int i; if(k==m){ for(i=0;i<=m;i++) printf("%d ",a[i]); printf("\n"); return; } else{ for