康拓展开
2015-04-27 12:43
218 查看
康拓展开
康拓展开在求字典序问题上是一个十分强大的算法首先,康拓展开是形如以下的式子
X=an∗(n−1)!+an−1∗(n−2)!+...+a1∗0!
下面介绍一下此式在康拓展开中的含义
首先我们假设有一个长为n的字符串s,下标从0开始
ai的值是在后i-1个字符中,其中比s[n-i]小的字符个数
那么在此字符串在所有的排列中,字典序比此字符串小的有X个
那么我们就可以快速解决一些字典序的问题
首先就是如上所说的求有多少个比这个字典序小的字符串数,代码如下
@Frosero #include <iostream> #include <cstring> using namespace std; long long mul(long long n){ if(n == 0 || n == 1) return n; return n * mul(n - 1); } long long KT(string &s){ //康拓展开 long long ans = 0; for(string::size_type i=0;i<s.size();i++){ long long ai = 0; for(string::size_type j=i+1;j<s.size();j++){ //计算ai if(s[i] > s[j]){ ai++; } } ans += ai * mul(s.size() - i - 1); } return ans; //若想求此字符串是第几小,则返回ans+1 } int main(){ string s = "CAB"; cout << KT(s); return 0; }
康拓展开的逆用:快速找到第K个字典序的排列
方法:我们可以从高位到低位依次推断系数an,代码如下
@Frosero #include <iostream> #include <cstring> #include <set> #include <map> #include <cstdlib> #include <algorithm> #include <cstdio> #include <cmath> #include <stack> #include <queue> #include <vector> #define eps 1e-6 #define INF 0x3f3f3f3f #define LL long long using namespace std; long long mul(long long n){ if(n == 0 || n == 1) return 1; return n * mul(n - 1); } bool used[25]; void inv_KT(long long k,long long len,long long *a){ k--; memset(used,false,sizeof(used)); int tot = 0; for(int i=len-1;i>=0;i--){ int ai = k / mul(i); //确定最高位的系数ai int cnt = 0; for(int j=1;;j++)if(!used[j]){ //只有未被使用的数字才加入计数cnt if(cnt == ai){ a[tot++] = j; used[j] = true; //used[i]表示数字i是否在前面已经被使用 break; //若已被使用则used[i]标记为true } cnt++; } k = k % mul(i); //确定余数,继续进行后面的运算 } } int main(){ long long K = 5,len = 3,a[25]; inv_KT(K,len,a); for(int i=0;i<len;i++) cout<<a[i]<<" "; return 0; }
一些补充:
目测这个算法只能计算没有重复字符的字符串
C++中长度为20的字符串几乎是我们能处理的极限(不考虑高精度,或者用JAVA写肯定是壕无压力处理几万长的字符串)
这里我们用数字来表示示例的顺序,实际中只要建立数字和字符的映射关系即可。这也是这个算法之所以强大之所在!
相关文章推荐
- HDOJ 题目1043 Eight(单向BFS,康拓展开,打表)
- [模板]康拓展开和他的逆运算
- 南阳理工OJ 139 我排第几个(康拓展开)
- poj 1077(康拓展开)
- QDU第二次月赛 排在第几个(康拓展开)
- HDU3567:Eight II(康拓展开+预处理) (B)
- NYOJ 题目143 第几是谁?(康拓展开)
- 康拓展开-----两个排列的位置之差
- 康拓展开及逆康拓展开
- 康拓展开和康拓逆展开
- nyoj139 我排第几个(康拓展开)
- 【牛客练习赛13】 A B C D【康拓展开】 E【DP or 记忆化搜索】 F 【思维】
- HDU1043:Eight HDU3567:Eight II(康拓展开+bfs搜索)
- 九宫重拍(bfs + 康拓展开)
- 【算法系列学习三】[kuangbin带你飞]专题二 搜索进阶 之 A-Eight 反向bfs打表和康拓展开
- qduoj 26 排在第几个 康拓展开
- 牛客练习赛13 D 幸运数字Ⅳ[康拓展开逆运算]
- 康拓展开和(逆康拓展开)
- POJ 1077 Eight (康拓展开) HDU 1043 Eight
- 康拓展开及应用