程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 應用C說話處理字符串全分列成績

應用C說話處理字符串全分列成績

編輯:關於C++

應用C說話處理字符串全分列成績。本站提示廣大學習愛好者:(應用C說話處理字符串全分列成績)文章只能為提供參考,不一定能成為您想要的結果。以下是應用C說話處理字符串全分列成績正文


成績
輸出一個字符串,打印出該字符串中字符的一切分列。例如輸出字符串abc,則輸入由字符a,b,c所能分列出來的一切字符串abc,acb,bac,bca,cab和cba

思緒
這是典范的遞歸求解成績,遞歸算法有四個特征:

  1.     必需有可到達的終止前提,不然法式墮入逝世輪回
  2.     子成績在范圍上比原成績小
  3.     子成績可經由過程再次遞歸挪用求解
  4.     子成績的解應能組分解全部成績的解

  5. 關於字符串的分列成績:
    假如能生成n-1個元素的全分列,就可以生成n個元素的全分列。關於只要一個元素的聚集,可以直接生玉成分列。所以全分列的遞歸終止前提很明白,只要一個元素時。我們可以剖析一下全分列的進程:

    •     起首,我們固定第一個字符a,求前面兩個字符bc的分列
    •     當兩個字符bc分列求好以後,我們把第一個字符a和前面的b交流,獲得bac,接著我們固定第一個字符b,求前面兩個字符ac的分列
    •     如今是把c放在第一個地位的時刻了,然則記住後面我們曾經把本來的第一個字符a和前面的b做了交流,為了包管此次c還是和本來處在第一個地位的a交流,我們在拿c和第一個字符交流之前,先要把b和a交流回來。在交流b和a以後,再拿c和處於第一名置的a停止交流,獲得cba。我們再次固定第一個字符c,求前面兩個字符b、a的分列
    •     既然我們曾經曉得怎樣求三個字符的分列,那末固定第一個字符以後求前面兩個字符的分列,就是典范的遞歸思緒了


    上面這張圖很清晰的給出了遞歸的進程:

    根本處理辦法
    辦法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; 
      } 
    

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved