Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 查找给定字符串中的所有重复子字符串_C++_String_Algorithm - Fatal编程技术网

C++ 查找给定字符串中的所有重复子字符串

C++ 查找给定字符串中的所有重复子字符串,c++,string,algorithm,C++,String,Algorithm,我最近遇到了一个面试问题: 查找给定字符串中最小大小为2的所有重复子字符串。 算法应该是有效的 #include <iostream> #include <algorithm> #include <iterator> #include <set> #include <string> using namespace std; int main() { typedef string::const_iterator iterato

我最近遇到了一个面试问题: 查找给定字符串中最小大小为2的所有重复子字符串。 算法应该是有效的

#include <iostream>
#include <algorithm>
#include <iterator>
#include <set>
#include <string>

using namespace std;

int main()
{
    typedef string::const_iterator iterator;
    string s("ABCFABHYIFAB");
    set<string> found;

    if (2 < s.size())
        for (iterator i = s.begin() + 1, j = s.end(); i != j; ++i)
            for (iterator x = s.begin(); x != i; ++x)
            {
                iterator tmp = mismatch(i, j, x).second;;
                if (tmp - x > 1)
                    found.insert(string(x, tmp));
            }

            copy(found.begin(), found.end(),ostream_iterator<string>(cout, "\n"));
}
下面给出了上述问题的代码,但它不是有效的

#include <iostream>
#include <algorithm>
#include <iterator>
#include <set>
#include <string>

using namespace std;

int main()
{
    typedef string::const_iterator iterator;
    string s("ABCFABHYIFAB");
    set<string> found;

    if (2 < s.size())
        for (iterator i = s.begin() + 1, j = s.end(); i != j; ++i)
            for (iterator x = s.begin(); x != i; ++x)
            {
                iterator tmp = mismatch(i, j, x).second;;
                if (tmp - x > 1)
                    found.insert(string(x, tmp));
            }

            copy(found.begin(), found.end(),ostream_iterator<string>(cout, "\n"));
}
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
int main()
{
typedef字符串::常量迭代器迭代器;
字符串s(“ABCFABHYIFAB”);
集发现;
如果(21)
插入(字符串(x,tmp));
}
复制(found.begin(),found.end(),ostream_迭代器(cout,“\n”);
}
我的问题是,是否有任何数据结构可以及时实现上述问题 O(N)的复杂性


如果您的答案是后缀树或散列,请详细说明。

这只是一个疯狂的想法,但值得一试(不过,它会消耗O(N)内存,其中N是主字符串的长度)。该算法不是O(N),但可能是可以优化的

这个想法是,您不想经常进行字符串比较。您可以收集读取数据的散列(例如,读取字符的ASCII代码的总和)并比较散列。如果散列相等,则字符串可能相等(稍后必须进行检查)。例如:

ABCAB

A -> (65)
B -> (131, 66)
C -> (198, 133, 67)
A -> (263, 198, 132, 65)
B -> (329, 264, 198, 131, 66)
因为您只对2+长度值感兴趣,所以必须忽略最后一个值(因为它始终对应于单个字符)

我们看到两个相等的值:131和198。131代表AB并显示该对,而198代表ABC和BCA,必须通过手动检查予以拒绝

这只是想法,而不是解决方案本身。可以扩展散列函数以说明字符在子字符串(或序列结构)中的位置。可以更改散列值的存储方法以提高性能(但会增加内存使用的成本)


希望我能帮上一点忙:)

如果分析字符串“aaaaaaaaaaaaaaaa”的输出,那么其中有O(n²)个字符,因此算法至少是O(n²)

要实现O(n²),只需为s的每个后缀(索引[1..n]、[2..n]、[3..n]、…、[n..n])构建。不管其中一个字符串是否没有自己的结束节点,只要计算每个节点的使用频率即可


最后,用count>1迭代每个节点并打印其路径。

我不知道后缀树如何获得所有重复的子字符串,字符串“mississippi”构建后缀树,如下所示:

对不起,我明白了。最后,在count>1的情况下迭代每个节点并打印其路径。“count”是这个子节点的数量

tree-->|---mississippi               m..mississippi
       |
       |---i-->|---ssi-->|---ssippi   i .. ississippi
       |       |         |
       |       |         |---ppi      issip,issipp,issippi
       |       |
       |       |---ppi                ip, ipp, ippi
       |
       |---s-->|---si-->|---ssippi    s .. ssissippi
       |       |        |
       |       |        |---ppi       ssip, ssipp, ssippi
       |       |
       |       |---i-->|---ssippi     si .. sissippi
       |               |
       |               |---ppi        sip, sipp, sippi
       |
       |---p-->|---pi                 p, pp, ppi
               |
               |---i                  p, pi

--- Suffix Tree for "mississippi" ---

如果我理解正确,你认为两个(相等大小)子串在输出中不同,如果它们的起始索引不同,而不是它们的内容不同,对后缀树进行读取,在我看来,Wiki是一个很好的开始:@重复子字符串是CS中非常常见的问题。你能把这个作为解决方案吗?这将是非常有帮助的网站访问者。干杯@正如我看到的,接受的答案在我的评论后包含相同的内容,所以我不想重复它作为答案。也许应该在接受的答案中添加一些链接。你是如何建立这棵树的?