让S和T给出字符串。然后我们在S中第一次出现T时从S中删除T,并将剩余的S串称为S1。同样,我们在S1中第一次出现T时从S1中删除T,并将剩余的S1字符串称为S2。重复这样做,直到Sk中没有子串T.
请注意,删除T后,我们可能在S中有一个子串T.什么是S的剩余字符串? (如果S为空,那就好了。)
约束:
例如,S =" aa abba b abba bab",T =" abba"。剩下的字符串是" ab"。
我想用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;
}
非常感谢。
答案 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)