C#查找“连接”排列

时间:2019-04-29 09:37:47

标签: c# permutation

我正在处理字典表,需要找出单词中所有可能的字符组合。感谢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

有人有什么想法要实现上述目标吗?

3 个答案:

答案 0 :(得分: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 :(得分: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++;
    }
}

答案 2 :(得分: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.
      } 
   }   
}