重复删除子字符串后,查找剩余的字符串

Find remaining string after deleting a substring repeately

本文关键字:字符串 查找 删除      更新时间:2023-10-16

令s和t作为字符串。然后,我们在s中首次出现t中从s中删除t,然后将其余的s串称为s1。同样,我们在S1中的第一次出现时从S1中删除t,并将其余的S1字符串称为S2。反复这样做,直到sk中没有子字符串t。

请注意,删除t后我们可能在s中具有一个子字符串t。剩余的s串是什么?(如果S为空,那很好。)

约束:

  • 1< =长度(s)< = 10^6。
  • 1< =长度(t)< = 100。

例如,s =" aa abba b abba bab",t =" abba"。其余的字符串为" ab"。

我正在考虑使用KMP在T上具有前缀。然后,当我们在s中找到字符串t时,我们必须将索引i和j(i和s for s,j for t)更改为新位置。但是,我不确定J(可能是我)应该是什么?字符串可能有很多片段。

我的方法正确吗?如果是这样,您能否给我详细的步骤,我该怎么做,尤其是J的新价值?我坚持J的价值。找到比赛后,我不知道我应该将J分配给什么。这是我不知道的算法的一部分。

这是我未完成的代码。

std::vector<int> make_prefix(std::string &t) {
    std::vector<int> prefix(t.length());
    prefix[0] = 0;
    for (int i = 1, j = 0; i < t.length(); )
        if (t[i] == t[j]) {
            prefix[i] = j + 1;
            ++i; ++j;
        }
        else if (j > 0)
            j = prefix[j - 1];
        else
            prefix[i++] = 0;
    return prefix;
}
std::string repeatRemoving(std::string s, std::string t) {
    std::vector<int> prefix = make_prefix(t);
    for (int i = 0, j = 0; i < s.length(); ) {
        if (s[i] == t[j]) {
            ++i;
            ++j;
        }
        else if (j > 0)
            j = prefix[j - 1];
        else
            ++i;
        if (j == (int)t.length()) {
            // What should go here after finding a match?
            // How can I adjust the values of i and j?
            // How can I mark the deleted characters in s?
        }
    }
    return s;
}

非常感谢。

我发现了代码。我需要2个阵列:

  • prev:在S上存储i索引的先前位置。最初是prev[i] = prev[i - 1]。当我们在i + length(T)位置找到匹配时,我们将设置prev[i + length(T) + 1] = i - 1(即我们指向新位置的prev i以跳过整个字符串T)。
  • jv:在S上的每个i位置存储j的值。

删除S中的所有T后,我们使用prev重建剩余的字符串。总体复杂性是O(n m)

这是整个代码:

std::string remaining_after_delete_repeatedly(std::string s, std::string t) {
    std::vector<int> prefix = make_prefix(t);
    s += "#";
    std::vector<int> prev(s.length());
    std::vector<int> jv(s.length());
    for (int i = 0; i < s.length(); prev[i] = i - 1, ++i);
    for (int i = 0, j = 0; i < s.length(); ) {
        if (s[i] == t[j]) {
            jv[i] = j;
            ++i;
            ++j;
        }
        else if (j > 0)
            j = prefix[j - 1];
        else
            jv[i++] = 0;
        if (j == (int)t.length()) {
            int u = i - 1;
            for (int k = 0; k < t.length(); ++k)
                u = prev[u];
            prev[i] = u;
            j = u < 0 ? 0 : jv[u] + 1;
        }
    }
    std::string answer(1, s.back());
    for (int i = prev[s.length() - 1]; i > -1; i = prev[i])
        answer += s[i];
    std::reverse(answer.begin(), answer.end());
    return answer.substr(0, answer.length() - 1);
}