加扰一个字符串

时间:2013-03-03 00:03:03

标签: c# string permutation

如何处理如下所示的字符串,以便实现所有可能的排列?有这样的努力的LINQ方法吗?我搜索过Google,但找不到任何内容。

STRING = "Little Red Riding Hood"

4 个答案:

答案 0 :(得分:2)

This是我过去使用的优秀排列库。这篇文章包含一个代码片段,我认为它可以很好地满足您的需求(我已经略微适应了):

var inputSet = myString.ToCharArray();
var P2 = new Permutations<char>(inputSet, 
      GenerateOption.WithRepetition);
string format2 = "Permutations of {{A A C}} with Repetition; size = {0}";
Console.WriteLine(String.Format(format2, P2.Count));
foreach(IList<char> p in P2) {
  Console.WriteLine(String.Format("{{{0} {1} {2}}}", p[0], p[1], p[2]));
}

答案 1 :(得分:1)

C ++标准模板库(STL)中有一些方法,但我相信这些方法无法从C#中访问(以任何有意义的方式)。我相信你必须为STL写一个小的C ++包装器并从C#调用它;或编码C#中的排列。

更新:

生成N个项目的所有排列是旅行商问题(TSP)的必要前奏。这方面的算法遍布整个网络,这将解释在各种可能的顺序和并行算法 en passant 中生成permutaions。

答案 2 :(得分:1)

您希望使用字符串的字符执行Knuth/Fisher-Yates shuffle

以下是一堆C#实现,您可以适应字符串而不是数组:Is using Random and OrderBy a good shuffle algorithm?

答案 3 :(得分:1)

这是一个完整的示例程序:

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication2
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            var sentences = new List<string>
            {
                "Little Red Riding Hood",
                "Three Little Pigs",
                "Jack and the Beanstalk"
            };

            foreach (var sentence in sentences)
            {
                Console.WriteLine("----------------------------------");

                foreach (var permutation in Permute(sentence.Split(' ')))
                {
                    foreach (string word in permutation)
                    {
                        Console.Write(word + " ");
                    }

                    Console.WriteLine();
                }
            }

            // If you want to put all the permutations for all the sentences into a List<string>, you can just do this:

            List<string> permutations = new List<string>();

            foreach (var sentence in sentences)
            {
                permutations.AddRange(Permute(sentence.Split(' ')).Select(perm => string.Join(" ", perm)));
            }

            Console.WriteLine("The total number of perms is: " + permutations.Count);
        }

        /// <summary>
        /// Provides a sequence of enumerators for obtaining all permutations of a sequence.
        /// Each enumeration in the returned sequence itself enumerates one of the permutations of the input sequence.
        /// Use two nested foreach statements to visit each item in each permuted sequence.
        /// </summary>

        public static IEnumerable<IEnumerable<T>> Permute<T>(IEnumerable<T> sequence)
        {
            return permute(sequence, sequence.Count());
        }

        // Returns an enumeration of enumerators, one for each permutation of the input.

        private static IEnumerable<IEnumerable<T>> permute<T>(IEnumerable<T> sequence, int count)
        {
            if (count == 0)
            {
                yield return new T[0];
            }
            else
            {
                int startingElementIndex = 0;

                foreach (T startingElement in sequence)
                {
                    IEnumerable<T> remainingItems = allExcept(sequence, startingElementIndex);

                    foreach (IEnumerable<T> permutationOfRemainder in permute(remainingItems, count - 1))
                    {
                        yield return concat<T>(new T[] { startingElement }, permutationOfRemainder);
                    }

                    ++startingElementIndex;
                }
            }
        }

        // Implements the recursive part of Permute<T>

        private static void permute<T>(T[] items, int item, T[] permutation, bool[] used, Action<T[]> output)
        {
            for (int i = 0; i < items.Length; ++i)
            {
                if (!used[i])
                {
                    used[i] = true;
                    permutation[item] = items[i];

                    if (item < (items.Length - 1))
                    {
                        permute(items, item + 1, permutation, used, output);
                    }
                    else
                    {
                        output(permutation);
                    }

                    used[i] = false;
                }
            }
        }

        // Enumerates over all items in the input, skipping over the item with the specified index.

        private static IEnumerable<T> allExcept<T>(IEnumerable<T> input, int indexToSkip)
        {
            int index = 0;

            foreach (T item in input)
            {
                if (index != indexToSkip)
                {
                    yield return item;
                }

                ++index;
            }
        }

        // Enumerates over contents of two lists sequentially.

        private static IEnumerable<T> concat<T>(IEnumerable<T> a, IEnumerable<T> b)
        {
            foreach (T item in a)
            {
                yield return item;
            }

            foreach (T item in b)
            {
                yield return item;
            }
        }
    }
}