检查给定的字符串是不是可以由从杂志文章中截取的一组字符创建

Posted

技术标签:

【中文标题】检查给定的字符串是不是可以由从杂志文章中截取的一组字符创建【英文标题】:Check if given string can be created by a set of characters cut out from magazine article检查给定的字符串是否可以由从杂志文章中截取的一组字符创建 【发布时间】:2011-09-02 09:19:27 【问题描述】:

“观察当你从杂志上剪下一个字符时,页面反面的字符也被删除了。给出一个算法来确定你是否可以通过从给定杂志上粘贴剪裁来生成给定的字符串。假设您将获得一个函数,该函数将针对任何给定的字符位置识别字符及其在页面背面的位置。”

我该怎么做?

我可以进行一些初始修剪,这样如果需要的角色只有一种被拾取的方式,它会在将子问题转为动态技术之前进行初始处理,但是在初始修剪之后呢?

时间和空间复杂度是多少?

【问题讨论】:

我的猜测是,您可以以某种方式将其简化为 Mincut/Maxflow,但我还不知道该怎么做。类似于使用字符组合作为图形中的链接和字符串作为流的方式。今晚晚些时候我将不得不更仔细地考虑这一点。 【参考方案1】:

正如@LiKao 所建议的,这可以使用最大流量来解决。为了构建网络,我们制作了两个顶点“层”:一层包含输入字符串中的所有不同字符,一层包含页面上的每个位置。如果该位置的一侧有该字符,则从一个字符到该位置创建一条容量为 1 的边。从每个位置到接收器的容量为 1 的边,从源到每个字符的边的容量等于输入字符串中该字符的重数。

例如,假设我们要在有四个位置的页面上搜索单词“FOO”:

pos    1 2 3 4
front  F C O Z
back   O O K Z

然后我们生成以下网络,忽略位置 4,因为它没有提供任何所需的字符。

现在,我们只需要判断是否有length("FOO") = 3或更多length("FOO") = 3的源到sink的流。

【讨论】:

这个解决方案是否与通过最大流量求解分配算法有关? @mcdowella:是的。这是解决将页面上的位置分配给输入字符串中的字符的问题。 我什至不明白这个问题。所以这意味着给你一个字符串 S,然后你进行切割,每次切割可以给你两个字符。把你切割的所有字符放在一起,看看这些字符是否可以等于S?你能帮忙澄清这个问题吗? @锤子 @Jack:不,重点是您只能使用每件作品一次,但您可以选择您想要的顺序以及每件作品的哪一面。 我也认为 max-flow 是解决这个练习的正确方法,但是,在 Skiena 的书中,这个练习列在动态编程部分。会不会有一个使用动态规划的空间和时间高效的解决方案?【参考方案2】:

可以直接使用动态规划。

我们得到了包含 n 个字母的字符串 s。我们有一组片段 P = p_1, ..., p_k。每件作品前p_i.f一个字母,后p_i.b一个字母。

用 f(j, p) 表示函数,如果可以使用 p \subseteq P 中的片段创建子字符串 s_1...s_j,则返回 true,否则返回 false。

以下重复成立: f(n, P) = f(n-1, P-p_1) | f(n-1, P-p_2) | ... | f(n-1, P-p_k)

简单地说,s 使用 P 中的所有片段的可行性,取决于子串 s_1...s_n-1 给定少一个片段的可行性,我们尝试删除所有可能的片段(当然在实践中我们不会必须逐个删除所有部分;我们只需要删除那些 p_i.f == s_n || p_i.b == s_n) 的部分。

初始条件是 f(1, P-p_1) = f(1, P-p2) = ... = true,假设我们已经先验(在线性时间内)检查了有足够的P中的字母覆盖s中的所有字母。

【讨论】:

P 的子集呈指数级增长,因此在我看来,对于某些输入,动态编程在这里可能不起作用。 是的,你是对的。在最坏的情况下,这将最终检查所有可能的子集。此外,递归关系也没有正确表述。【参考方案3】:

虽然这个问题可以表述为 Maxflow 问题,如已接受的答案所示,但将其表述为二部图中的最大基数匹配问题更简单、更有效。像 Dinic's 这样的 Maxflow 算法比像 Hopcroft–Karp algorithm 这样的特殊情况算法慢。

二分图是通过将给定字符串的每个字符的两条边添加到一个切口来形成的,每边一条边。然后我们运行 Hopcroft–Karp。最后,我们简单的检查一下匹配的基数是否等于字符串的长度。

有关使用 JGraphT 的工作实现(在 Scala 中),请参阅我的 GitHub。

我想提出一个更有效的DP解决方案,因为Skiena的书在DP部分有这个问题,但到目前为止还没有发现任何问题。

【讨论】:

以上是关于检查给定的字符串是不是可以由从杂志文章中截取的一组字符创建的主要内容,如果未能解决你的问题,请参考以下文章

检查数组是不是至少包含 PHP 中的一组值

如何编写 R 脚本来检查直线;即,对于任何给定的行,一组列中的所有值是不是具有相同的值

检查Java中的一组字符串中的包含

检查 Swift 对象是不是是给定元类型的实例

查找用户是不是在给定坐标的给定距离内

检查是不是存在一组相关行