给定两个已排序的向量a
和b
,找到a
和b
的某些排列之和的所有向量,并且这些向量一旦排序就是唯一的。
您可以通过以下方式创建一个搜索到的向量:
a
和向量b
的排列。c[i]=a[i]+b[i]
。c
。我有兴趣找到一组b
- 排列,这些排列会产生一整套独特的c
向量。
示例0 :a='ccdd'
和b='xxyy'
给出求和向量:'cycydxdx'
,'cxcxdydy'
,'cxcydxdy'
请注意b
:'xyxy'
和'yxyx'
的排列相等,因为在这两种情况下,“box c”和“box d”都只得到一个'x'
和一个'y'
。
我想这类似于将M
球放入M
方框中(每个方框一个),其中一组球和方框相同。
更新:鉴于字符串a='aabbbcdddd'
和b='xxyyzzttqq'
,您的问题将是4个方框中的10个球。有4个不同的盒子,大小分别为2,3,1和4.这些球是完全无法区分的。
示例1:鉴于字符串为a='xyy'
和b='kkd'
可能的解决方案:'kkd'
,'dkk'
。
原因:我们发现b
的所有唯一排列都是'kkd'
,'kdk'
和'dkk'
。但是,根据我们的约束,两个第一个排列被认为是相等的,因为不同的索引映射到字符串'y'
中的相同字符a
。
示例2:鉴于字符串为a='xyy'
和b='khd'
可能的解决方案:'khd'
,'dkh'
,'hkd'
。
示例3:鉴于字符串为a='xxxx'
和b='khhd'
可能的解决方案:'khhd'
。
我可以使用在Wikipedia/Permutation上描述的Narayana Pandita算法来解决生成唯一候选b
排列的问题。
第二部分接缝更难。我最好的方法是将两个字符串成对连接到一个列表,对其进行排序并将其用作查找集中的键。 ('xx'
+ 'hd'
加入→'xh','xd'
排序→'xd','xh'
)。
由于我的M
通常非常大,并且由于字符串中的相似性很常见,因此我目前生成的b
排列方式比实际通过设置过滤器更多{{1}}排列。我希望有一个算法直接生成正确的算法。欢迎任何改进。
答案 0 :(得分:2)
要生成可能重复元素的k组合(multiset),以下内容可能很有用:A Gray Code for Combinations of a Multiset (1995)。
对于递归解决方案,请尝试以下操作:
计算每个角色出现的次数。假设它们是x1 x2 ... xm,对应于m个不同的字符。
然后你需要找到所有可能的有序对(y1 y2 ... ym),这样
0< = yi< = xi
和Sum yi = k。
这里yi是我出现的字符的次数。
想法是,修复char 1出现的次数(y1)。然后递归地生成剩余的k-y1的所有组合。
伪码:
List Generate (int [] x /* array index starting at 1*/,
int k /* size of set */) {
list = List.Empty;
if (Sum(x) < k) return list;
for (int i = 0; i <= x[1], i++) {
// Remove first element and generate subsets of size k-i.
remaining = x.Remove(1);
list_i = Generate(remaining, k-i);
if (list_i.NotEmpty()) {
list = list + list_i;
} else {
return list;
}
}
return list;
}
编辑前:
如果我理解正确,你需要查看字符串a,查看恰好出现一次的符号。说有这样的符号。然后,您需要生成b的所有可能排列,其中包含k个元素并映射到相应位置的那些符号。其余的你可以忽略/填写你认为合适的。
我记得在这里发布了C#代码:How to find permutation of k in a given length?
我假设xxyy只会给出一个唯一的字符串,那些只出现一次的字符串就是“区别”。
例如a=xyy, b=add
区别点是x
因此,您选择长度为1的“添加”。这些会为您提供a
和d
。
因此,您需要add
和dad (or dda)
。
a=xyyz b=good
区别点是x和z
因此,您生成长度为2的b的排列
go
og
oo
od
do
gd
dg
为您提供7种独特的排列。
这有帮助吗?我的理解是否正确?
答案 1 :(得分:0)
好的,对不起,我从来没能清楚地解释这个问题,但这是一个解决方案。
我们需要两个函数combinations
和runvector(v)
。 combinations(s,k)
生成长度为k
的多集的唯一组合。对于s='xxyy'
,这些将是['xx','xy','yy']
。 runvector(v)
将表示为排序向量的多集转换为更简单的结构,即运行向量。 runvector('cddeee')=[1,2,3]
。
要解决这个问题,我们将使用递归生成器。我们贯穿了适用于box1的所有组合以及对其余框的追索,禁止我们已经选择的值。要完成禁止,combinations
将在所有通话中保持一种比特。
在python中,方法如下:
def fillrest(banned,out,rv,b,i):
if i == len(rv):
yield None
return
for comb in combinations(b,rv[i],banned):
out[i] = comb
for rest in fillrest(banned,out,rv,b,i+1):
yield None
def balls(a,b):
rv = runvector(a)
banned = [False for _ in b]
out = [None for _ in rv]
for _ in fill(out,rv,0,b,banned):
yield out[:]
>>> print list(balls('abbccc','xyyzzz'))
[['x', 'yy', 'zzz'],
['x', 'yz', 'yzz'],
['x', 'zz', 'yyz'],
['y', 'xy', 'zzz'],
['y', 'xz', 'yzz'],
['y', 'yz', 'xzz'],
['y', 'zz', 'xyz'],
['z', 'xy', 'yzz'],
['z', 'xz', 'yyz'],
['z', 'yy', 'xzz'],
['z', 'yz', 'xyz'],
['z', 'zz', 'xyy']]
输出采用'box'格式,但很容易合并回简单字符串:'xyyzzzz'
,'xyzyzz'
...