在字符串中查找随机顺序子字符串
Posted
技术标签:
【中文标题】在字符串中查找随机顺序子字符串【英文标题】:Finding Randomly Order Substring in String 【发布时间】:2018-04-17 14:34:01 【问题描述】:对于我的第一部分问题,我们已经给出了一长串输入,我们必须计算它的出现次数。 例如。
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
如果您请为给定的示例编写代码,并附上您使用的任何新功能的解释/说明链接。
【问题讨论】:
你是在问如何找到一个字符串中的所有子串排列?input
和 find
是否只包含大写字母?
@Ron 将子串组排列在一起。我已经更新了问题,例如。如果 find 是 AXB 则输入将始终将它们组合在一起,例如。 AXBNMNNOBXANBMOAXB
@arsho 是的。输入总是大写
@Gengestu 感谢您的编辑
【参考方案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;
【讨论】:
非常感谢 :) 我理解你的大部分方法。你能解释一下“建立要找到的角色的地图”吗? @Slava AFAIK 这是 O(NM) 其中 N 和 M 是每个字符串的大小。 我认为添加条件if( part[c] > to_find[c] ) break;
可以显着优化它
@UtsoRoy for (auto e : string_to_find)
循环遍历string_to_find
中的每个字符。 ++to_find[e]
表示将该字符存储在映射中并增加该字符映射到的 int 的值。当你说++to_find['a']
如果'a'
不在地图中,那么它会将它放在地图中并给它一个值1。如果'a'
已经在地图中,那么它只会增加值。
@Slava 也许。我必须对其进行分析,看看分支机构的成本是否值得。【参考方案2】:
一种简单的方法是遍历给定的字符串并搜索目标字符串。
在每个块中,我们需要对部分进行排序并比较它是否与目标字符串匹配。
#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(n2)
【讨论】:
如果你喜欢它,放弃投票并接受它作为答案:)【参考方案3】:一种解决方案是找到搜索字符串和子字符串的规范表示。有两种快速方法是可能的。
1) 对子字符串进行排序。 2) 计算字母的直方图。
选项 2 可以通过在搜索窗口中增加传入字母的直方图 bin 并减少传出字母的 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)。
【讨论】:
以上是关于在字符串中查找随机顺序子字符串的主要内容,如果未能解决你的问题,请参考以下文章