想象一下,我的两个朋友Wendy
和Hunter
为他们的孩子Henry
命名。请注意,可以通过合并每个父母姓名的字符子集(而不更改其顺序),从Henry
和Hunter
创建名称Wendy
。更具体地说:
"henry"
是"hnr"
和"ey"
,其中每个父母姓名中的字符顺序保持不变。
"hnr"
是"hunter"
中字符的子集,其中字符保持有序。
我们可以对"ey"
和"wendy"
进行类似的观察。
问题:
是否有一种简单的方法可以验证是否可以通过两个父名称生成任何给定名称而不只是为一对夫妇生成所有可能的子名称?
即。我可以轻松检查isSpecialName("Dan", "Jane", "Adam")
- 是否可以通过名称"Dan"
和"Jane"
以这种方式创建"Adam"
,而无需针对所有合并的有序字符子集进行检查"Jane"
和"Adam"
?
答案 0 :(得分:5)
我们想说,如果字符串a
对字符串b
和字符串c
特殊,我们就要证明这是正确的。
一个重要的观察是,如果a
和b
的{{1}}特殊,则移除c
的最后一个字符,获得a
,它仍然是a'
和b
特别。也就是说:
c
这是次优模式,因此我们可以使用动态编程算法。
如果if isSpecial(a, b, c) is True
then isSpecial(a[0..-1], b, c) is True
和f(i, j, k)
a[0..i]
特殊,则b[0..j]
代表{/ 1}}。
c[0..k]
我写了一个小程序来验证这个算法。但代码并不像算法那么简洁。
时间复杂度a[i] == b[j] => f(i, j, k) sub pattern is f(i-1, j-1, k)
a[i] == c[k] => f(i, j, k) sub pattern is f(i-1, j, k-1)
otherwise => f(i, j, k) sub pattern is f(i, j, k-1) & f(i, j-1, k)
,空间复杂度O(la*lb*lc)
O(la*lb*lc)
答案 1 :(得分:1)
从一开始就开始匹配时只有两种或更少的可能性:要么以母亲的名义或父亲的名义进行第一次出现。以后的事件也可以起作用,但是如果他们这样做,那么第一次出现也必须起作用。所以我们可以编写一个非常简单的算法:
function isSpecialName(child, mother, father) {
child = child.toLowerCase();
mother = mother.toLowerCase();
father = father.toLowerCase();
for (let i = 0, x = 0, y = 0; i < child.length; i++) {
let m = mother.indexOf(child[i], x), f = father.indexOf(child[i], y);
if (m < 0 && f < 0)
return false;
if (f < 0)
x = m + 1;
else if (m < 0)
y = f + 1;
else if (isSpecialName(
child.substr(i + 1), mother.substr(m + 1), father.substr(y)))
return true;
else
y = f + 1;
}
return true;
}