C++ 有没有更好的方法来排列字符串? void排列(字符串元素,整数中间,整数结尾) { 静态整数计数; 如果(中间==结束){ 特别是你想要的 void排列(字符串元素,整数中间,整数结尾) { 整数计数=0; while(下一个置换(elems.begin()+mid,elems.end()) 你为什么不试试std::next\u permutation()或std::prev\u permutation() ?
链接:C++ 有没有更好的方法来排列字符串? void排列(字符串元素,整数中间,整数结尾) { 静态整数计数; 如果(中间==结束){ 特别是你想要的 void排列(字符串元素,整数中间,整数结尾) { 整数计数=0; while(下一个置换(elems.begin()+mid,elems.end()) 你为什么不试试std::next\u permutation()或std::prev\u permutation() ?,c++,algorithm,string,permutation,C++,Algorithm,String,Permutation,链接: 一个简单的例子: void permute(string elems, int mid, int end) { int count = 0; while(next_permutation(elems.begin()+mid, elems.end())) cout << << ++count << " : " << elems << endl; } 任何生成置换的算法都将在多项式时间内运行,因为n长度字符串中
一个简单的例子:
void permute(string elems, int mid, int end)
{
int count = 0;
while(next_permutation(elems.begin()+mid, elems.end()))
cout << << ++count << " : " << elems << endl;
}
任何生成置换的算法都将在多项式时间内运行,因为n长度字符串中字符的置换数是
(n!)
。也就是说,有一些非常简单的生成置换的就地算法。请查看。任何使用或生成所有置换的算法都需要O(N!*N)时间,O(N!)至少生成所有置换,O(N!)使用结果,这非常慢。请注意,打印字符串也是O(N)阿法克
在一秒钟内,无论您使用何种方法,您实际上只能处理最多10或11个字符的字符串。因为11!*11=439084800次迭代(在大多数机器上,在一秒钟内处理这么多个字符就是在推它)和12!*12=574801920次迭代。因此,即使是最快的实现,在12个字符上也需要大约30到60秒
Factorial的增长速度太快,您不可能希望通过编写更快的实现来获得任何东西,您最多只能获得一个字符。因此,我建议您使用Prason的建议。它很容易编写,而且速度相当快。尽管坚持使用您的代码也完全可以
<>我建议你小心不要在字符串中无意中有多余的字符,比如空字符。因为这样会使你的代码的N个因子变慢。 < P>这是一个C++中的非递归算法,从维基百科条目中得到。对于字符串<代码> s >代码>长度<代码> N<代码>,对于任何<代码> K<代码>
0
到n!-1
包括,以下修改s
以提供唯一的置换(即,不同于为该范围内的任何其他k值生成的置换)。要生成所有置换,请对s的原始值上的所有n!k
值运行它
123
132
213
231
312
321
#包括
无效置换(整数k、字符串和s)
{
对于(int j=1;j
这里
交换(s,i,j)
交换字符串s的位置i和j。我最近写了一个置换算法。它使用类型为T(模板)的向量它不是字符串,而且速度也不是很快,因为它使用递归,而且有很多复制。但是,也许你可以从代码中获得一些灵感。你可以找到代码。显著提高性能的唯一方法是找到一种方法,首先避免迭代所有排列
置换是一个不可避免的慢操作(O(n!),或者更糟,取决于您对每个置换所做的操作),不幸的是,您所能做的任何事情都不会改变这一事实
另外,请注意,当启用优化时,任何现代编译器都会使递归变得平坦,因此手动优化带来的性能收益会进一步降低。我想说第二点。他引用的算法与已经提供的各种置换枚举算法的工作方式有根本不同。它不会生成n个对象的所有置换,而是在给定int的情况下生成一个独特的特定置换eger介于0和n!-1之间。如果您只需要一个特定的排列,它比枚举所有排列然后选择一个排列要快得多
即使您确实需要所有排列,它也提供了单个排列枚举算法无法提供的选项。我曾经编写了一个蛮力密码破解程序,尝试将字母分配给数字。对于base-10
问题,这是足够的,因为只有10!
排列可以尝试。但是对于base-11
问题需要几分钟,而base-12
问题需要将近一个小时
我用一个简单的I=0--to--N-1
for循环替换了我一直使用的置换枚举算法,使用了Permaquid引用的算法。结果只是稍微慢了一点。但随后我将整数范围分成四分之一,同时运行四个for循环,每个循环在一个单独的线程中。在我的四核处理器上,resulting程序的运行速度几乎是原来的四倍
正如使用置换枚举算法查找单个置换是困难的一样,生成所有置换集的划定子集也是困难的。Permaquid引用的算法使这两种方法都非常容易值得研究
#include <algorithm>
void permutation(int k, string &s)
{
for(int j = 1; j < s.size(); ++j)
{
std::swap(s[k % (j + 1)], s[j]);
k = k / (j + 1);
}
}
//就地洗牌字符数组
无效洗牌(字符数组[],int n)
{
对于(;n>1;n--)
{
//拾取要移动到终点的随机元素
int k=rand()%n;//0是否要运行所有置换,或计算置换的数量
对于前者,按照其他人的建议使用std::next_permutation
。每个置换都需要O(N)时间(但摊销时间较少),除了调用帧之外没有内存,而递归函数则需要O(N)时间和O(N)内存。整个过程是O(N!),正如其他人所说,你不能做得比这更好,因为你只能得到O(X)不管怎么说,在没有量子计算机的情况下,在不到O(X)的时间内完成一个程序的结果
对于后者,您只需要知道字符串中有多少唯一的元素
// In-place shuffle of char array
void shuffle(char array[], int n)
{
for ( ; n > 1; n--)
{
// Pick a random element to move to the end
int k = rand() % n; // 0 <= k <= n-1
// Simple swap of variables
char tmp = array[k];
array[k] = array[n-1];
array[n-1] = tmp;
}
}
查找重复元素的操作限制了速度,对于char
s,可以使用查找表在O(N)时间内完成。我不认为这更好,但它确实有效并且不使用递归:
big_int count_permutations( string s ) {
big_int divisor = 1;
sort( s.begin(), s.end() );
for ( string::iterator pen = s.begin(); pen != s.end(); ) {
size_t cnt = 0;
char value = * pen;
while ( pen != s.end() && * pen == value ) ++ cnt, ++ pen;
divisor *= big_int::factorial( cnt );
}
return big_int::factorial( s.size() ) / divisor;
}
#包括
#包括
#包括
::圣
// In-place shuffle of char array
void shuffle(char array[], int n)
{
for ( ; n > 1; n--)
{
// Pick a random element to move to the end
int k = rand() % n; // 0 <= k <= n-1
// Simple swap of variables
char tmp = array[k];
array[k] = array[n-1];
array[n-1] = tmp;
}
}
big_int count_permutations( string s ) {
big_int divisor = 1;
sort( s.begin(), s.end() );
for ( string::iterator pen = s.begin(); pen != s.end(); ) {
size_t cnt = 0;
char value = * pen;
while ( pen != s.end() && * pen == value ) ++ cnt, ++ pen;
divisor *= big_int::factorial( cnt );
}
return big_int::factorial( s.size() ) / divisor;
}
#include <iostream>
#include <stdexcept>
#include <tr1/cstdint>
::std::uint64_t fact(unsigned int v)
{
::std::uint64_t output = 1;
for (unsigned int i = 2; i <= v; ++i) {
output *= i;
}
return output;
}
void permute(const ::std::string &s)
{
using ::std::cout;
using ::std::uint64_t;
typedef ::std::string::size_type size_t;
static unsigned int max_size = 20; // 21! > 2^64
const size_t strsize = s.size();
if (strsize > max_size) {
throw ::std::overflow_error("This function can only permute strings of size 20 or less.");
} else if (strsize < 1) {
return;
} else if (strsize == 1) {
cout << "0 : " << s << '\n';
} else {
const uint64_t num_perms = fact(s.size());
// Go through each permutation one-by-one
for (uint64_t perm = 0; perm < num_perms; ++perm) {
// The indexes of the original characters in the new permutation
size_t idxs[max_size];
// The indexes of the original characters in the new permutation in
// terms of the list remaining after the first n characters are pulled
// out.
size_t residuals[max_size];
// We use div to pull our permutation number apart into a set of
// indexes. This holds what's left of the permutation number.
uint64_t permleft = perm;
// For a given permutation figure out which character from the original
// goes in each slot in the new permutation. We start assuming that
// any character could go in any slot, then narrow it down to the
// remaining characters with each step.
for (unsigned int i = strsize; i > 0; permleft /= i, --i) {
uint64_t taken_char = permleft % i;
residuals[strsize - i] = taken_char;
// Translate indexes in terms of the list of remaining characters
// into indexes in terms of the original string.
for (unsigned int o = (strsize - i); o > 0; --o) {
if (taken_char >= residuals[o - 1]) {
++taken_char;
}
}
idxs[strsize - i] = taken_char;
}
cout << perm << " : ";
for (unsigned int i = 0; i < strsize; ++i) {
cout << s[idxs[i]];
}
cout << '\n';
}
}
}
// find all the permutations of a string
// using Knuth radnom shuffling algorithm!
#include <iostream>
#include <string>
template <typename T, class Func>
void permutation(T array, std::size_t N, Func func)
{
func(array);
for (std::size_t n = N-1; n > 0; --n)
{
for (std::size_t k = 0; k <= n; ++k)
{
if (array[k] == array[n]) continue;
using std::swap;
swap(array[k], array[n]);
func(array);
}
}
}
int main()
{
while (std::cin.good())
{
std::string str;
std::cin >> str;
permutation(str, str.length(), [](std::string const &s){
std::cout << s << std::endl; });
}
}
//***************anagrams**************//
//************************************** this code works only when there are no
repeatations in the original string*************//
#include<iostream>
using namespace std;
int counter=0;
void print(char empty[],int size)
{
for(int i=0;i<size;i++)
{
cout<<empty[i];
}
cout<<endl;
}
void makecombination(char original[],char empty[],char comb[],int k,int& nc,int size)
{
nc=0;
int flag=0;
for(int i=0;i<size;i++)
{
flag=0; // {
for(int j=0;j<k;j++)
{
if(empty[j]==original[i]) // remove this code fragment
{ // to print permutations with repeatation
flag=1;
break;
}
}
if(flag==0) // }
{
comb[nc++]=original[i];
}
}
//cout<<"checks ";
// print(comb,nc);
}
void recurse(char original[],char empty[],int k,int size)
{
char *comb=new char[size];
int nc;
if(k==size)
{
counter++;
print(empty,size);
//cout<<counter<<endl;
}
else
{
makecombination(original,empty,comb,k,nc,size);
k=k+1;
for(int i=0;i<nc;i++)
{
empty[k-1]=comb[i];
cout<<"k = "<<k<<" nc = "<<nc<<" empty[k-1] = "<<empty[k-1]<<endl;//checks the value of k , nc, empty[k-1] for proper understanding
recurse(original,empty,k,size);
}
}
}
int main()
{
const int size=3;
int k=0;
char original[]="ABC";
char empty[size];
for(int f=0;f<size;f++)
empty[f]='*';
recurse(original,empty,k,size);
cout<<endl<<counter<<endl;
return 0;
}
#include <iostream>
using namespace std;
void swap(char *a, char *b)
{
char tmp = *a;
*a = *b;
*b = tmp;
}
int partition(char arr[], int start, int end)
{
int x = arr[end];
int i = start - 1;
for(int j = start; j <= end-1; j++)
{
if(arr[j] <= x)
{
i = i + 1;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i+1], &arr[end]);
return i+1;
}
void quickSort(char arr[], int start, int end)
{
if(start<end)
{
int q = partition(arr, start, end);
quickSort(arr, start, q-1);
quickSort(arr, q+1, end);
}
}
int findCeilIndex(char *str, int firstIndex, int n)
{
int ceilIndex;
ceilIndex = firstIndex+1;
for (int i = ceilIndex+1; i < n; i++)
{
if(str[i] >= str[firstIndex] && str[i] <= str[ceilIndex])
ceilIndex = i;
}
return ceilIndex;
}
void reverse(char *str, int start, int end)
{
while(start<=end)
{
char tmp = str[start];
str[start] = str[end];
str[end] = tmp;
start++;
end--;
}
}
void permutate(char *str, int n)
{
quickSort(str, 0, n-1);
cout << str << endl;
bool done = false;
while(!done)
{
int firstIndex;
for(firstIndex = n-2; firstIndex >=0; firstIndex--)
{
if(str[firstIndex] < str[firstIndex+1])
break;
}
if(firstIndex<0)
done = true;
if(!done)
{
int ceilIndex;
ceilIndex = findCeilIndex(str, firstIndex, n);
swap(&str[firstIndex], &str[ceilIndex]);
reverse(str, firstIndex+1, n-1);
cout << str << endl;
}
}
}
int main()
{
char str[] = "mmd";
permutate(str, 3);
return 0;
}
void permute(const char* str, int level=0, bool print=true) {
if (print) std::cout << str << std::endl;
char temp[30];
for (int i = level; i<strlen(str); i++) {
strcpy(temp, str);
temp[level] = str[i];
temp[i] = str[level];
permute(temp, level+1, level!=i);
}
}
int main() {
permute("1234");
return 0;
}
#include<iostream.h>
#include<conio.h>
#include<string.h>
int c=1,j=1;
int fact(int p,int l)
{
int f=1;
for(j=1;j<=l;j++)
{
f=f*j;
if(f==p)
return 1;
}
return 0;
}
void rev(char *a,int q)
{
int l=strlen(a);
int m=l-q;
char t;
for(int x=m,y=0;x<q/2+m;x++,y++)
{
t=a[x];
a[x]=a[l-y-1];
a[l-y-1]=t;
}
c++;
cout<<a<<" ";
}
int perm(char *a,int f,int cd)
{
if(c!=f)
{
int l=strlen(a);
rev(a,2);
cd++;
if(c==f)return 0;
if(cd*2==6)
{
for(int i=1;i<=c;i++)
{
if(fact(c/i,l)==1)
{
rev(a,j+1);
rev(a,2);
break;
}
}
cd=1;
}
rev(a,3);
perm(a,f,cd);
}
return 0;
}
void main()
{
clrscr();
char *a;
cout<<"\n\tEnter a Word";
cin>>a;
int f=1;
for(int o=1;o<=strlen(a);o++)
f=f*o;
perm(a,f,0);
getch();
}
**// Prints all permutation of a string**
#include<bits/stdc++.h>
using namespace std;
void printPermutations(string input, string output){
if(input.length() == 0){
cout<<output <<endl;
return;
}
for(int i=0; i<=output.length(); i++){
printPermutations(input.substr(1), output.substr(0,i) + input[0] + output.substr(i));
}
}
int main(){
string s = "ABC";
printPermutations(s, "");
return 0;
}
void permute(string prefix, string suffix, vector<string> &res) {
if (suffix.size() < 1) {
res.push_back(prefix);
return;
}
for (size_t i = 0; i < suffix.size(); i++) {
permute(prefix + suffix[i], suffix.substr(0,i) + suffix.substr(i + 1), res);
}
}
int main(){
string str = "123";
vector<string> res;
permute("", str, res);
}
template <typename Cont1_t, typename Cont2_t>
void permute(typename Cont1_t prefix,
typename Cont1_t::iterator beg, typename Cont1_t::iterator end,
Cont2_t &result)
{
if (beg == end) {
result.insert(result.end(), prefix);
return;
}
for (auto it = beg; it != end; ++it) {
prefix.insert(prefix.end(), *it);
Cont1_t tmp;
for (auto i = beg; i != end; ++i)
if (i != it)
tmp.insert(tmp.end(), *i);
permute(prefix, tmp.begin(), tmp.end(), result);
prefix.erase(std::prev(prefix.end()));
}
}
int main()
{
string str = "123";
vector<string> rStr;
permute<string, vector<string>>("", str.begin(), str.end(), rStr);
vector<int>vint = { 1,2,3 };
vector<vector<int>> rInt;
permute<vector<int>, vector<vector<int>>>({}, vint.begin(), vint.end(), rInt);
list<long> ll = { 1,2,3 };
vector<list<long>> vlist;
permute<list<long>, vector<list<long>>>({}, ll.begin(), ll.end(), vlist);
}