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

时间:2017-03-15 18:47:50

标签: c++ arrays string algorithm search

让S和T给出字符串。然后我们在S中第一次出现T时从S中删除T,并将剩余的S串称为S1。同样,我们在S1中第一次出现T时从S1中删除T,并将剩余的S1字符串称为S2。重复这样做,直到Sk中没有子串T.

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

约束:

  • 1< = length(S)< = 10 ^ 6。
  • 1 <=长度(T)<= 100。

例如,S =&#34; aa abba b abba bab&#34;,T =&#34; abba&#34;。剩下的字符串是&#34; ab&#34;。

我想用KMP在T上有一个前缀。然后当我们在S中找到一个字符串T时,我们必须将索引i和j(i为S,j为T)更改为new位置。但是,我不确定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;
}

非常感谢。

1 个答案:

答案 0 :(得分:0)

我想出了代码。我还需要2个阵列:

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

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

以下是整个代码:

O(n m)