【问题标题】:Algorithm if there is a string including subsequences A and B but not F如果存在包含子序列 A 和 B 但不包含 F 的字符串的算法
【发布时间】:2018-09-14 11:34:07
【问题描述】:

我正在为以下问题寻找一种有效的算法:

我们得到三个字符串 A、B 和 F 作为输入,我们需要判断是否存在一个字符串 X,使得 A 和 B 是 X 的子序列,但 F 不是。算法的输出应该是“是”或“否”。

字符串的子序列是可以通过从原始字符串中删除一些字母而不改变剩余字母的顺序来创建的任何字符串。

例如,如果 A = "aabab", B = "bbaa" 和 F = "baba",算法应该输出“Yes”,因为 "aabbaab" 有 A 和 B 作为子序列,但没有 F。

有什么想法吗?

【问题讨论】:

  • 即使 KMP/Needle in the Stack 也能做到!
  • 能否请您说明如何将 KMP 应用于此问题?
  • 欢迎来到 Stack Overflow。你能告诉我们你到目前为止所做的尝试吗?
  • 请参阅here 了解 KPM。看起来不错
  • 我知道对不起,我没有和你说话。我在打字时看不到你的消息。

标签: algorithm subsequence


【解决方案1】:

XAB最小 超序列,如果 X 可以依次匹配 A 和/或 B 的字母。

AB 的每个超序列都是 F 的超序列当且仅当 A的每个最小超序​​列> 和 BF 的超序列。

一个接受 AB 的最小超序列的 DFA 可以很容易地用最多 |A|*|B| 状态构造,每个状态对应于两个字符串中的一对兼容位置。见https://en.wikipedia.org/wiki/Deterministic_finite_automatonhttps://en.wikipedia.org/wiki/Powerset_construction

如果有一个 AB 的超序列不是 F 的超序列,那么有一条通过此 DFA 的路径不是 F 的超序列。

将通过 DFA 的路径的成本定义为作为路径子序列的 F 的最长前缀的长度,即您将从 F 匹配的字符数 沿路。

然后,由于 DFA 是非循环的,您可以使用 Dijkstra 算法或最佳优先搜索来找到到达每个状态的最低成本。见https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm

如果任何接受状态具有小于 |F| 的最小成本,则存在 AB 的超序列也不是 F 的超序列。

整个操作的复杂度是O(|A|*|B|)

实现这一点的最简单方法是使用 |A|+1 x |B|+1 矩阵作为 DFA——就像您使用的那样用于 LCS 计算。矩阵中的每个单元格都是一个状态。发现时以最低成本填充单元格。

【讨论】:

    【解决方案2】:

    现在我对这个问题有了更多的思考,我找到了一个非常简单有效的解决方案。 ;) 这个问题比我最初想象的要容易得多。它可以在线性 O(|A| + |B|) 时间内求解,无需任何额外空间。

    这个想法是遍历 F 的字符并始终将 A 和 B 的最大部分带到超序列中,以便不超过 F 的当前前缀是它的子序列。下面的 c++ 代码阐明了这个想法:

    int i = 0, j = 0;
    for (int k = 0; k < F.size()-1; k++) {
        while (i < A.size() && A[i] != F[k]) i++;
        while (j < B.size() && B[j] != F[k]) j++;
        i++; j++;
        if (i >= A.size() && j >= B.size()) {
            cout << "YES";
            return 0;
        }
    }
    cout << "NO";
    

    【讨论】:

      猜你喜欢
      • 2014-03-23
      • 2018-11-16
      • 1970-01-01
      • 2021-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-06
      • 2017-03-16
      相关资源
      最近更新 更多