这可能更容易用代码示例解释,我有以下两个函数。第一个创建给定长度(size
)和字符(group
)的所有字符串集
private List<string> generateSets(int size, IList<string> group)
{
List<string> ret = new List<string>();
int[] indices = new int[size];
for (int i = 0; i < size; i++) indices[i] = i;
ret.Add((size > 0 ? group[indices[0]] : "") +
(size > 1 ? group[indices[1]] : "") +
(size > 2 ? group[indices[2]] : "") +
(size > 3 ? group[indices[3]] : "") +
(size > 4 ? group[indices[4]] : ""));
while (indices[0] < (group.Count - size))
{
for (int i = size - 1; i >= 0; i--)
{
if (indices[i] < (group.Count - (indices.Length - i)))
{
indices[i]++;
for (int j = i + 1; j < size; j++)
{
indices[j] = indices[j - 1] + 1;
}
break;
}
}
ret.Add((size > 0 ? group[indices[0]] : "") +
(size > 1 ? group[indices[1]] : "") +
(size > 2 ? group[indices[2]] : "") +
(size > 3 ? group[indices[3]] : "") +
(size > 4 ? group[indices[4]] : ""));
}
return (ret);
}
第二个函数根据所有可能的匹配压缩一组集合:
private List<string> compressSets(List<string> sets, List<string> possible)
{
List<string> working = null;
List<string> ret = new List<string>();
List<int> indices = new List<int>() { 0 };
List<int> indicesLow = null;
while (indices.Count < possible.Count)
{
working = new List<string>(sets);
for (int i = 0; i < indices.Count; i++)
{
for (int w = working.Count - 1; w >= 0; w--)
{
if (this.ContainsAll(possible[indices[i]], working[w])) working.RemoveAt(w);
}
}
if (working.Count < 1)
{
if ((indicesLow == null) || (indicesLow.Count > indices.Count))
{
for (int i = 0; i < indices.Count; i++)
{
ret.Add(possible[indices[i]]);
}
return (ret);
}
}
for (int i = indices.Count - 1; i >= 0; i--)
{
if (indices[i] < (possible.Count - (indices.Count - i)))
{
indices[i]++;
for (int j = i + 1; j < indices.Count; j++)
{
indices[j] = indices[j - 1] + 1;
}
break;
}
}
if (indices[0] >= (possible.Count - indices.Count))
{
for (int i = 0; i < indices.Count; i++) indices[i] = i;
indices.Add(indices.Count);
}
}
return (ret);
}
public bool ContainsAll(string set, string subset)
{
/*foreach (T item in subset)
{
if (!set.Contains(item)) return (false);
}
return (true);*/
for (var i = 0; i < subset.Length; i++)
{
if (set.IndexOf(subset[i]) < 0) return (false);
}
return (true);
}
例如:
List<string> group = new List<string>();
group.Add("A");
group.Add("B");
group.Add("C");
group.Add("D");
group.Add("E");
group.Add("F");
List<string> sets3 = this.generateSets(3, group);
List<string> sets4 = this.generateSets(4, group);
List<string> sets = this.compressSets(sets3, sets4);
for (int i = 0; i < sets.Count; i++)
{
Debug.WriteLine(sets[i]);
}
将输出:
ABCD
ABCE
ABCF
ADEF
BDEF
CDEF
这是一组最小的4个字符长度的字符串,包含每个3个字符长度的字母A-F组合,而不考虑它们出现的顺序。这很好用,似乎可以正确地扩展一个主要警告:初始集大小,目标集大小和结果集中所需匹配字符数的每次增加都需要指数级更长。有没有办法让这个更快或更优的算法来实现这个任务?
答案 0 :(得分:1)
嗯...组合,N个项目一次取X.
在你的例子中,6个项目(A-F)一次4个
所以...请参阅这里的答案...