首页  编辑  

字符串的排列组合

Tags: /超级猛料/String.字符串处理/   Date Created:

字符串的排列组合

var

 // doAbort: boolean;  // Time consuming, so may want abort option

 resultList: TStringlist;

// Simple integer factorial handles 12! = 479,001,600 max

// Doesn't complain if n negative, just returns 1

function factorial(n: integer): integer;

var

 i, x: integer;

begin

 x := 1;

 if n > 1 then

   for i := 2 to n do  x := x * i;

 result := x;

end;

// Number of permutations

//  = length! / product of (  (count of unique characters)! )

function numberOfPermutations(theWord: string): integer;

var

 char1, char2: string[1];

 len, i, j: integer;

 maxPermutations: integer;  // If no characters duplicated

 prodOfCharCount: integer;  // Product of count factorial

 posCounted: array of boolean;   // Mark counted positions

 countOfChar: array of integer;  // Count of unique characters

 upWord: string;  // theWord in all caps

begin

 upWord := upperCase(theWord);  // Ignore differences in case

 len := length(upWord);

 setLength(posCounted, len);  // Allocate memory for array

 setLength(countOfChar, len); // Allocate memory for array

 // Initialize the arrays for marking and counting

 for i := 0 to len-1 do begin  

   posCounted[i] := false;

   countOfChar[i] := 1;   //  Product of these must not be zero

 end;

 // Go thru the word and count appearances of each letter

 for i := 0 to len-1 do begin      // Get a letter

   char1 := copy(upWord, i+1, 1);

   for j := i+1 to len-1 do begin    // Check remaining letters

     char2 := copy(upWord, j+1, 1);

     if not posCounted[j] then         // Skip if previously matched

       if char1 = char2 then begin  // Found match to count

         inc(countOfChar[i]);   // Count the character

         posCounted[j] := true;   // Mark as counted to avoid recount

       end;

   end;

 end;

 // Replace character counts by factorials of character counts

 for i := 0 to len-1 do countOfChar[i] := factorial(countOfChar[i]);

 prodOfCharCount := 1;  // Initialize

 for i := 0 to len-1 do  prodOfCharCount :=  

   prodOfCharCount*countOfChar[i];

 maxPermutations := factorial(len);

 numberOfPermutations := maxPermutations div prodOfCharCount;

end;

// Returns str with the last i characters rotated j times

// Needed by permute procedure below

function subRotate(i, j: integer; str: string): string;

var

 len, rotStrPos, rotChrPos, n: integer;

 baseStr: string;

begin

 len := length(str);

 rotStrPos := len - i + 1;  // First char to rotate

 rotChrPos := rotStrPos + j;  // New first char after rotation

 baseStr := copy(str, 1, rotStrPos-1); // No change to this part

 // Append rotated characters to base string

 for n := rotChrPos to len do

   insert(copy(str, n, 1), baseStr, length(baseStr)+1);

 for n := rotStrPos to rotChrPos-1 do

   insert(copy(str, n, 1), baseStr, length(baseStr)+1);

 result := baseStr;

end;

// Fills global resultList with all permutations of aWord

procedure permute(aWord: string);

// Algorithm:

// Put wordIn into resultList

// For i = 2 to length(wordIn)

//   For each item in the resultList

//     For j = 1 to i-1

//       Add R(i,j, item) to listToAdd

//     Next j

//   Next item

//   Add listToAdd to resultList

// Next i

// R(i,j,item) returns the item string with the last i characters rotated j times

//   R(3,2, abcd) = adbc

var

 listToAdd: TStringlist;

 i, j, k, len: integer;

begin

 resultList.clear;  // Clear global var for reuse

 len := length(aWord);

 listToAdd := TStringlist.create;

 listToAdd.duplicates := dupIgnore;

 listToAdd.sorted := true;

 resultList.append(aWord);  // See Algorithm comments above

 for i := 2 to len do begin

   for j := 0 to resultList.count-1 do begin

     for k := 1 to i-1 do begin

       listToAdd.append(subRotate(i, k, resultList[j]));

{       if doAbort then begin  // Good place to allow abort

         resultList.clear;

         listToAdd.free;

         exit;

       end;

       application.processMessages; }

     end;

   end;

   resultList.addStrings(listToAdd);

   listToAdd.clear;

 end;

 listToAdd.free;

end;