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

C++ 重复删除子字符串后查找剩余字符串,c++,arrays,string,algorithm,search,C++,Arrays,String,Algorithm,Search,设S和T为字符串。然后,当T在S中第一次出现时,我们将T从S中移除,并将剩余的S字符串称为S1。同样,我们在S1中第一次出现T时从S1中删除T,并将S1的剩余字符串称为S2。重复这样做,直到Sk中没有子串T 请注意,在删除T之后,S中可能有一个子字符串T。S的剩余字符串是什么?(如果S为空则可以。) 约束条件: (10) j=前缀[j-1]; 其他的 前缀[i++]=0; 返回前缀; } std::string repeatRemoving(std::string s,std::string

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

请注意,在删除T之后,S中可能有一个子字符串T。S的剩余字符串是什么?(如果S为空则可以。)

约束条件:

  • (10) j=前缀[j-1]; 其他的 前缀[i++]=0; 返回前缀; } std::string repeatRemoving(std::string s,std::string t){ std::vector prefix=make_prefix(t); 对于(int i=0,j=0;i0) j=前缀[j-1]; 其他的 ++一,; 如果(j==(int)t.length()){ //找到匹配项后,应该到这里做什么? //如何调整I和j的值? //如何在s中标记已删除的字符? } } 返回s; }
    非常感谢。

    我算出了密码。我还需要2个阵列:

    • prev
      :存储
      i
      索引在
      S
      上的先前位置。最初
      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(nm)

    以下是全部代码:

    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);
    }
    
    重复删除后剩下的字符串(std::string s,std::string t){ std::vector prefix=make_prefix(t); s+=“#”; std::vector prev(s.length()); std::vector jv(s.length()); 对于(int i=0;i0) j=前缀[j-1]; 其他的 jv[i++]=0; 如果(j==(int)t.length()){ int u=i-1; 对于(int k=0;k-1;i=prev[i]) 答案+=s[i]; std::reverse(answer.begin(),answer.end()); 返回answer.substr(0,answer.length()-1); }
    就像在查看KMP后的仓促猜测一样,我认为关键在于记住以前部分匹配的开始和长度,直到找到一个不属于任何正在进行的匹配的字符来消除它们。您不能使用
    regex_replace()
    删除所有这些字符吗?它们可能重叠,S=“abababacc”,t=“abc”->“abababcc”,不正确,一次通过replace@KennyOstrom正是我所想的。然而,我很难实现这一点。这似乎比我想象的要复杂。“T可能会分裂成许多碎片。@巴尔马正如肯尼·奥斯特罗姆所说,在移除T之后,可能会形成一个新的字符串T。
    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);
    }