C ++在具有特定位置的字符串中查找非重叠子字符串

C++ find non-overlapping substring in string with position specifics

我想弄清楚如何找到字符串中非重叠子串的计数,但仅限于那些距离相同的子串。我设法获得了非重叠子串的数量,但这只是要求的子集。

示例: 我有一个字符串“aaaaaaaaaabaaaaaaba”,我想计算非重叠子串“aa”的数量,但只计算距离乘以 2 的那些。

标准非重叠代码returns8,这是正确的(aa aa aa aa aa b aa aa aa ba - 用空格区分结果)。它在位置 0,2,4,6,8,11,13,15.

找到子串

当我尝试实现距离要求时,我遇到了问题。 所需的计数应为 7,省略位置 11 的 'a' 并继续位置 12 (aa aa aa aa aa ba aa aa ab a) ...再次用空格区分结果,'a'在位置 11 应该形成子字符串 'ba' 与 'b' 在位置 10

我尝试使用模数来识别正确的位置并仅计算从模数结果为 0 的位置开始的子字符串,但是通过执行我的代码,处理仅在第 5 次出现时停止,在 'b' 之前中间的,忽略后面的。

wrong: aa aa aa aa aa b aa aa aa b a

good:  aa aa aa aa aa ba aa aa ab a

同样,它应该适用于其他尺寸,例如,查找“aaa”,因此结果将是 4“aaa aaa aaa aba aaa aab a”而不是 5“aaa aaa aaa ab aaa aaa ba”

string str = "aaaaaaaaaabaaaaaaba";
    string sub = "aa";
    int count = 0;

    for (size_t offset = str.find(sub); offset != std::string::npos;
            offset = str.find(sub, offset + sub.length()))
    {
        int pos = offset % sub.length();
        if (pos == 0)
        {
            ++count;
            cout << "offset: " << offset << " count: " << count << endl;
        }
    }
    cout << "count: " << count << endl;
    return 0;

你的循环做错了事:它试图从最后找到的偏移量 + 2(aa 的长度)开始 find 子字符串。

第一个aa找奇数后,以后的所有尝试也都找奇数

这个有效:

for (size_t offset = str.find(sub); offset != std::string::npos;
    offset = str.find(sub, offset + 1))

我整天都在寻找解决方案,在发布我的问题几分钟后,我找到了解决方案(墨菲定律)。

诀窍是添加 'else' 语句并将偏移量移回模余数:

if (pos == 0)
        {
            ++count;
            cout << "offset: " << offset << " count: " << count << endl;
        }
else
        {
            offset = offset - pos;
            cout << "pos: " << pos << endl;
        }

我建议仅使用 std::string::find 来查找第一个子字符串,然后每次迭代仅执行 sub.size()

这是一个在 str 中的当前子字符串上使用 std::string_view 的示例:

#include <string>
#include <string_view>
#include <iostream>

int main() {
    std::string str = "aaaaaaaaaabaaaaaaba";
    //                 ! ! ! ! ! X ! ! X X
    //                 0 2 4 6 81012141618
    std::string sub = "aa";
    int count = 0;

    for(size_t offset = str.find(sub);
        offset < str.size() - sub.size();
        offset += sub.size())             // just step sub.size() here
    {
        if(sub == std::string_view(str.c_str() + offset, sub.size()))
            std::cout << "offset: " << offset << " count: " << ++count << '\n';
    }

    std::cout << "count: " << count << '\n';
}

输出:

offset: 0 count: 1
offset: 2 count: 2
offset: 4 count: 3
offset: 6 count: 4
offset: 8 count: 5
offset: 12 count: 6
offset: 14 count: 7
count: 7