應用C說話處理字符串全分列成績。本站提示廣大學習愛好者:(應用C說話處理字符串全分列成績)文章只能為提供參考,不一定能成為您想要的結果。以下是應用C說話處理字符串全分列成績正文
成績
輸出一個字符串,打印出該字符串中字符的一切分列。例如輸出字符串abc,則輸入由字符a,b,c所能分列出來的一切字符串abc,acb,bac,bca,cab和cba
思緒
這是典范的遞歸求解成績,遞歸算法有四個特征:
關於字符串的分列成績:
假如能生成n-1個元素的全分列,就可以生成n個元素的全分列。關於只要一個元素的聚集,可以直接生玉成分列。所以全分列的遞歸終止前提很明白,只要一個元素時。我們可以剖析一下全分列的進程:
上面這張圖很清晰的給出了遞歸的進程:
根本處理辦法
辦法1:順次從字符串中掏出一個字符作為終究分列的第一個字符,對殘剩字符構成的字符串生玉成分列,終究成果為掏出的字符和殘剩子串全分列的組合。
#include <iostream> #include <string> using namespace std; void permute1(string prefix, string str) { if(str.length() == 0) cout << prefix << endl; else { for(int i = 0; i < str.length(); i++) permute1(prefix+str[i], str.substr(0,i)+str.substr(i+1,str.length())); } } void permute1(string s) { permute1("",s); } int main() { //method1, unable to remove duplicate permutations. cout << "method1" << endl; permute1("ABA"); }
長處:該辦法易於懂得,但沒法移除反復的分列,如:s="ABA",會生成兩個“AAB”。
辦法2:應用交流的思惟,詳細見實例,但該辦法不如辦法1輕易懂得。
#include <iostream> #include <string> #include <cstdio> using namespace std; void swap(char* x, char* y) { char tmp; tmp = *x; *x = *y; *y = tmp; } /* Function to print permutations of string This function takes three parameters: 1. String 2. Starting index of the string 3. Ending index of the string. */ void permute(char *a, int i, int n) { int j; if (i == n) printf("%s\n", a); else { for (j = i; j <= n; j++) { if(a[i] == a[j] && j != i) //為防止生成反復分列,當分歧地位的字符雷同時不再交流 continue; swap((a+i), (a+j)); permute(a, i+1, n); swap((a+i), (a+j)); //backtrack } } } int main() { //method2 cout << "method2" << endl; char a[] = "ABA"; permute(a,0,2); return 0; }
兩種辦法的生成成果:
method1 ABA AAB BAA BAA AAB ABA method2 ABA AAB BAA
上面來看ACM標題實例
示例標題
標題描寫
標題描寫:
給定一個由分歧的小寫字母構成的字符串,輸入這個字符串的一切全分列。
我們假定關於小寫字母有'a' < 'b' < ... < 'y' < 'z',並且給定的字符串中的字母曾經依照從小到年夜的次序分列。
輸出:
輸出只要一行,是一個由分歧的小寫字母構成的字符串,已知字符串的長度在1到6之間。
輸入:
輸入這個字符串的一切分列方法,每行一個分列。請求字母序比擬小的分列在後面。字母序以下界說:
已知S = s1s2...sk , T = t1t2...tk,則S < T 等價於,存在p (1 <= p <= k),使得
s1 = t1, s2 = t2, ..., sp - 1 = tp - 1, sp < tp成立。
樣例輸出:
abc
樣例輸入:
abc
acb
bac
bca
cab
cba
提醒:
每組樣例輸入停止後要再輸入一個回車。
ac代碼
#include <stdio.h> #include <stdlib.h> #include <string.h> struct seq { char str[7]; }; struct seq seqs[721]; int count; void swap(char *str, int a, int b) { char temp; temp = str[a]; str[a] = str[b]; str[b] = temp; } void permutation_process(char *name, int begin, int end) { int k; if (begin == end - 1) { strcpy(seqs[count].str, name); count ++; }else { for (k = begin; k < end; k ++) { swap(name, k, begin); permutation_process(name, begin + 1, end); swap(name, k, begin); } } } int compare(const void *p, const void *q) { const char *a = p; const char *b = q; return strcmp(a, b); } int main() { char name[7]; int i, len; while (scanf("%s", name) != EOF) { count = 0; len = strlen(name); permutation_process(name, 0, len); qsort(seqs, count, sizeof(seqs[0]), compare); for (i = 0; i < count; i ++) { printf("%s\n", seqs[i].str); } printf("\n"); } return 0; }
/**************************************************************
Problem: 1120
User: wangzhengyi
Language: C
Result: Accepted
Time:710 ms
Memory:920 kb
****************************************************************/
去失落反復的全分列
上述代碼有個缺點,就是會形成反復數據的輸入,例如abb這類字符串,上述法式跑結束果如圖:
因為全分列就是從第一個數字起,每一個數分離與它前面的數字交流,我們先測驗考試加個如許的斷定——假如一個數與前面的數字雷同那末這兩個數就不交流了。例如abb,第一個數與前面兩個數交流得bab,bba。然後abb中第二個數和第三個數雷同,就不消交流了。然則對bab,第二個數和第三個數分歧,則須要交流,獲得bba。因為這裡的bba和開端第一個數與第三個數交流的成果雷同了,是以這個辦法不可。
換種思想,對abb,第一個數a與第二個數b交流獲得bab,然後斟酌第一個數與第三個數交流,此時因為第三個數等於第二個數,所以第一個數就不再用與第三個數交流了。再斟酌bab,它的第二個數與第三個數交流可以處理bba。此時全分列生成終了!
如許,我們獲得在全分列中去失落反復的規矩:
去重的全分列就是從第一個數字起,每一個數分離與它前面非反復湧現的數字交流。
貼出下面ac代碼的去再版本:
#include <stdio.h> #include <stdlib.h> #include <string.h> struct seq { char str[7]; }; struct seq seqs[721]; int count; int is_swap(char *str, int begin, int k) { int i, flag; for (i = begin, flag = 1; i < k; i ++) { if (str[i] == str[k]) { flag = 0; break; } } return flag; } void swap(char *str, int a, int b) { char temp; temp = str[a]; str[a] = str[b]; str[b] = temp; } void permutation_process(char *name, int begin, int end) { int k; if (begin == end - 1) { strcpy(seqs[count].str, name); count ++; }else { for (k = begin; k < end; k ++) { if (is_swap(name, begin, k)) { swap(name, k, begin); permutation_process(name, begin + 1, end); swap(name, k, begin); } } } } int compare(const void *p, const void *q) { const char *a = p; const char *b = q; return strcmp(a, b); } int main() { char name[7]; int i, len; while (scanf("%s", name) != EOF) { count = 0; len = strlen(name); permutation_process(name, 0, len); qsort(seqs, count, sizeof(seqs[0]), compare); for (i = 0; i < count; i ++) { printf("%s\n", seqs[i].str); } printf("\n"); } return 0; }