C#查找“连接”排列

问题描述 投票:0回答:3

我正在编写一个字典表,需要找出一个单词中所有可能的字符组合。感谢https://codereview.stackexchange.com/questions/28248/implement-a-function-that-prints-all-possible-combinations-of-the-characters-in,我到目前为止工作到了以下:

    public List<string> findAllOccurance(string str)
    {
        var results = from e in Range(0, BigInteger.Pow(2, str.Length))
             let p =
                 from b in Enumerable.Range(1, str.Length)
                 select (e & BigInteger.Pow(2, b - 1)) == 0 ? (char?)null : str[b - 1]
             select string.Join(string.Empty, p);

        return results.ToList();
    }

    public IEnumerable<BigInteger> Range(BigInteger start, BigInteger count)
    {
        while (count-- > 0)
        {
            yield return start++;
        }
    }

将“abc”传递给上面的函数会返回:

a
b
ab
c
ac
bc
abc

问题是我实际上只想找出“原始顺序”中的“连接”排列,例如“abc”应该只返回

a
b
c
ab
bc
abc

有谁知道我应该改变什么来实现上述目标?

c# permutation
3个回答
2
投票

通过“连接”排列 - 您可以有效地查找从长度1到字符串全长的所有子字符串。这可以通过两个for循环很容易地完成。可以使用Linq的Distinct()方法删除重复项。

public List<string> findAllOccurance(string str)
{
    List<string> result = new List<string>();
    for (int i = 1; i <= str.Length; i++)
    {
      for (int j=0; j <= str.Length-i; j++)
        result.Add(str.Substring(j,i));
    }
    return result.Distinct().ToList();
}

注意 - 如果你确实想要返回一个空字符串 - 你可以修改外部循环从0开始,或者只是在创建列表实例后手动添加它。修改循环将导致添加str.Length空字符串,并且当您知道只返回1个空字符串时,还会为Distinct()做更多工作。

List<string> result = new List<string>();
result.Add(String.Empty);
for (int i = 1; i <= str.Length; i++)
.....

1
投票

我不知道我是否理解“连接”正确...也许你可以简单地检查一下潜在的结果是否是原始字符串的一部分......这样的事情:

public List<string> findAllOccurance(string str)
{
    var results = from e in Range(0, BigInteger.Pow(2, str.Length))
         let p =
             from b in Enumerable.Range(1, str.Length)
             select (e & BigInteger.Pow(2, b - 1)) == 0 ? (char?)null : str[b - 1]
         let p2 = string.Join(string.Empty, p)
         where str.Contains(p2)
         select p2;

    return results.ToList();
}

public IEnumerable<BigInteger> Range(BigInteger start, BigInteger count)
{
    while (count-- > 0)
    {
        yield return start++;
    }
}

1
投票

对于您的代码,您正在执行按位运算以查找所有可能的子集。对于abc的情况,你的字符串长度是3.所以可能的子集= 2 ^ 3 = 8.将它们写下来并将最右边的位与最左边的索引匹配:

Possible cases: 
0 0 0     // gives nothing
0 0 1     // gives 'a' (valid)
0 1 0     // gives 'b' (valid)
0 1 1     // gives 'ab' (valid)
1 0 0     // gives 'c' (valid)
1 0 1     // gives 'ac' (invalid as there is a 0 inbetween and not connected)
1 1 0     // gives 'bc' (valid)
1 1 1     // gives 'abc' (valid)

以上就是我所理解的你认为是连接的东西。您可以使用两个循环轻松执行检查:

int max_size = BigInteger.Pow(2, str.Length);
int str_size = str.Length;
for(int i = 0; i < max_size; ++i) 
{ 
    string ans = "";
    for(j = 0; j < str_size; ++j) 
   { 
      // We check if the jth bit is set, we print the jth element from the string.
       if(i & (1 << j)) 
           ans += str[j];
       } 
       else {
           if(ans.Length > 0){
               // this means we have already added a character and then the next consecutive bit is '0'
               ans = "";
               break;
           }
       }
      if(ans != ""){
           Console.Writeline(ans); // we print the set. you can control this anyway you want.
      } 
   }   
} 
© www.soinside.com 2019 - 2024. All rights reserved.