我正在编写一个字典表,需要找出一个单词中所有可能的字符组合。感谢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
有谁知道我应该改变什么来实现上述目标?
通过“连接”排列 - 您可以有效地查找从长度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++)
.....
我不知道我是否理解“连接”正确...也许你可以简单地检查一下潜在的结果是否是原始字符串的一部分......这样的事情:
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++;
}
}
对于您的代码,您正在执行按位运算以查找所有可能的子集。对于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.
}
}
}