在字符串中查找随机顺序子字符串

时间:2018-04-17 14:34:01

标签: c++ string substring

对于我的第一部分问题,我们给出了一长串输入,我们必须计算它的出现次数。 例如。

Input = AXBHAAGHXAXBH
Find = AXBH
Output = 2

这可以通过使用string.find("term")循环来实现。例如。

#include <string>
#include <iostream>
int main()
{
   int occurrences = 0;
   std::string::size_type pos = 0;
   std::string inputz = "AXBHAAGHXAXBH";
   std::string target = "AXBH";
   while ((pos = inputz.find(target, pos )) != std::string::npos) {
          ++ occurrences;
          pos += target.length();
   }
   std::cout << occurrences << std::endl;

}

但是,我不知道如何做第二部分,它需要考虑随机结构: 随机结构是指我们发现的任何方向。重要说明:查找事件始终组合在一起,但可以具有不同的结构。 我不想使用案例,因为一些样本发现太大,例如。查找 AXBHNMB 会有太多需要考虑的案例,并希望采用更一般的方法。

Eg. AXBH is find, then AXHB is also acceptable for the occurence

一个恰当的例子:

Input = AXBHAAGHXAXBH**ABHX**NBMN**AHBX**
Find = AXBH
Output = 4

如果您为给定的示例编写代码,请更喜欢,并为您使用的任何新功能添加解释/说明链接。

3 个答案:

答案 0 :(得分:1)

你是正确的,检查所有排列会花费很多时间。幸运的是,我们不需要这样做。我们可以做的是存储字符串以在std::map<char, int> / std::unordered_map<char, int>中查找,然后从字符串中获取子字符串以进行搜索,将这些字符串转换为相同类型的地图并查看这些地图是否相等。这样可以在不关心订单的情况下使用比较,它只是确保我们拥有正确数量的每个字符。所以我们会有像

这样的东西
int main()
{
    std::string source = "AHAZHBCHZCAHAHZEHHAAZHBZBZHHAAZAAHHZBAAAAHHHHZZBEWWAAHHZ ";
    std::string string_to_find = "AAHHZ";
    int counter = 0;

    // build map of the characters to find
    std::unordered_map<char, int> to_find;
    for (auto e : string_to_find)
        ++to_find[e];

    // loop through the string, grabbing string_to_find chunks and comparing
    for (std::size_t i = 0; i < source.size() - string_to_find.size();)
    {
        std::unordered_map<char, int> part;
        for (std::size_t j = i; j < string_to_find.size() + i; ++j)
            ++part[source[j]];

        if (to_find == part)
        {
            ++counter;
            i += string_to_find.size();
        }
        else
        {
            ++i;
        }
    }

    std::cout << counter;
}

答案 1 :(得分:0)

一种天真的方法是迭代给定的字符串并搜索目标字符串。

在每个块中,我们需要对该部分进行排序,并比较它是否与目标字符串匹配。

#include <string>
#include <iostream>
#include <algorithm>

int main()
{
    int occurrences = 0;
    std::string::size_type pos = 0;
    std::string inputz = "AXBHAAGHXAXBH**ABHX**NBMN**AHBX**";
    std::string target = "AXBH";
    std::sort(target.begin(), target.end());
    int inputz_length = inputz.length();
    int target_length = target.length();
    int i=0;
    for(i=0; i<=inputz_length-target_length; i++)
    {
        std::string sub = inputz.substr(i, target_length);
        std::sort(sub.begin(), sub.end());
        if (target.compare(sub) == 0)
        {
            std::cout << i<<"-->"<< target<<"-->" << sub << std::endl;
            occurrences++;
            i=i+target_length;
        }
    }
    std::cout << occurrences << std::endl;
    return 0;
}

输出:

0-->ABHX-->ABHX
9-->ABHX-->ABHX
15-->ABHX-->ABHX
27-->ABHX-->ABHX
4

额外功能:使用algorithm头文件中的sort功能。

时间复杂度:超过O(n 2

答案 2 :(得分:0)

一种解决方案是为搜索字符串和子字符串找到规范表示。两种快速方法是可能的。

1)对子字符串进行排序。 2)计算字母的直方图。

可以通过递增输入字母的直方图区间并递减搜索窗口中输出字母的区间来逐步计算选项2。

在更新直方图bin时,还可以检查此特定更新是否切换整体匹配:

// before adding the incoming letter
if (h[incoming] == target[incoming]) matches--;
else if (++h[incoming] == target[incoming]) matches++;
// before subtracting outgoing letter
if (h[outgoing] == target[outgoing]) matches--;
else if (--h[outgoing] == target[outgoing]) matches++; 

if (matches == number_of_unique_letters) occurences++;

然后整体复杂性变为O(n)。