使用c ++从由字符串组成的文件中查找所有可能的公共子字符串

Posted

技术标签:

【中文标题】使用c ++从由字符串组成的文件中查找所有可能的公共子字符串【英文标题】:Finding all possible common substrings from a file consisting of strings using c++ 【发布时间】:2012-02-03 11:35:55 【问题描述】:

我正在尝试从由不同长度的字符串组成的文件中查找所有可能的常见字符串。谁能帮帮我?

例如输入文件已排序:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC    
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG
AAAAAAAATTAGGCTGGG
AAAAAAAATTGAAACATCTATAGGTC
AAAAAAACTCTACCTCTCT
AAAAAAACTCTACCTCTCTATACTAATCTCCCTACA

我想要的输出是:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC    
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG
AAAAAAAATTAGGCTGGG
AAAAAAAATTGAAACATCTATAGGTC
AAAAAAACTCTACCTCTCTATACTAATCTCCCTACA

[编辑] 作为任何其他行的子字符串的每一行都应该被删除。

【问题讨论】:

好吧,我本来打算对这个问题投反对票,但只会要求详细说明你的问题。我花了一段时间才明白你的问题。 您输入的字母是否仅限于 A T C G ? 我不明白为什么你想要的输出是这样的。所有输入之间唯一的公共子字符串是“AAAAAAA”。你能解释更多吗? 您到底想知道什么?我们应该给你写一个程序吗?你完全不知道如何解决这个问题并想要一个算法吗?到目前为止,您尝试了什么(如果您尝试过)? 看起来你想丢弃所有作为另一行前缀的行,对吗? 【参考方案1】:

基本上对于每一行,与下一行比较,看下一行是否更短,或者下一行的子字符串是否不等于当前行。如果这是真的,那么这条线是唯一的。这可以通过单次线性传递来完成,因为列表已排序:任何包含条目子字符串的条目都将跟随该条目。

非算法优化(微优化)是避免使用创建新字符串的 substr。我们可以简单地比较另一个字符串,就像它被截断一样,而无需实际创建截断字符串。

vector<string> unique_lines;
for (unsigned int j=0; j < lines.size() - 2; ++j)

    const string& line = lines[j];
    const string& next_line = lines[j + 1];

    // If the line is not a substring of the next line,
    // add it to the list of unique lines.
    if (line.size() >= next_line.size() || 
        line != next_line.substr(0, line .size()))
        unique_lines.push_back(line);


// The last line is guaranteed to not be a substring of any
// previous line as the lines are sorted.
unique_lines.push_back(lines.back());

// The desired output will be contained in 'unique_lines'.

【讨论】:

【参考方案2】:

我的理解是你想找到子字符串并想删除这样的字符串,它是任何字符串的子字符串。 为此,您可以使用 strstr 方法来查找字符串是否是另一个字符串的子字符串。 希望这会有所帮助..

【讨论】:

嗯,我知道他想删除任何重复的子字符串。这就是你想说的吗? 正如 Ashutosh 所说,我正在尝试删除作为任何其他字符串的子字符串的此类字符串。谢谢大家 问题被标记为 c++,因此 std::string::find 将是一个更有用的答案。【参考方案3】:

嗯,这可能不是解决您的问题的最快解决方案,但似乎很容易实施。您只需保留一个字符直方图,该直方图将代表字符串的签名。对于您读取的每个字符串(以空格分隔),您计算每个字符的数量,如果没有任何其他字符串具有每个字符的相同数量,则将其存储在您的答案中。让我来说明一下:

aaa bbb aabb aaa

这里我们只有两个可能的输入字母,所以,我们只需要一个大小为 2 的直方图。

aaa - hist[0] = 3, hist[1] = 0 :新的 - 添加到答案中 bbb - hist[0] = 0, hist[1] = 3 : 新的 - 添加到答案中 aabb - hist[0] = 2, hist[1] = 2 : 新的 - 添加到答案中 ab - hist[0] = 1, hist[1] = 1 : 新的 - 添加到答案中

aaa - hist[0] = 3, hist[1] = 0 :已经存在!不要添加到答案中。

实现的瓶颈将是直方图比较,并且有很多可能的实现。

最简单的方法是简单的线性搜索,遍历您之前的所有答案并与当前的直方图进行比较,存储时间为 O(1),搜索时间为 O(n)。如果您有一个大文件,则需要数小时才能完成。

一种更快但实施起来更麻烦的方法是使用哈希表来存储您的答案,并使用直方图签名生成哈希码。在这里解释这种方法会很麻烦。

【讨论】:

以上是关于使用c ++从由字符串组成的文件中查找所有可能的公共子字符串的主要内容,如果未能解决你的问题,请参考以下文章

让 IntelliJ 知道属性文件

倒回多边形的索引

检查合并的单元格是不是为空白

从由外部脚本生成的元素中删除 DOM 元素

如何从由 SQL 查询填充的列表框中获取信息?

卸载使用 DllImport 加载的 DLL