c ++中最长的非重复子字符串

时间:2015-06-20 15:21:58

标签: c++ algorithm substring

我正在尝试找到没有重复字符的最长子字符串。 我有一个布尔矢量来跟踪256个ascii字符。

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

using namespace std;

int main()
{
    string s = "aaaaaaaaaaaaasadfrhtytbgrbrsvsrhvsg";
    vector<bool> v(256, false);
    int j = 0, len = 0, index = 0;

    for(int i = 0; i < s.length(); i++)
    {
        if(!v[s[i]])
        {
            j++;

            if(j > len)
            { 
                len = j;
                index = i - j;
            }

            v[s[i]] = true;
        }
        else
        {
            j = 0;
            v.clear();
        }
    }

    cout << s.substr(index, len) + " " << len << endl;
}

我可以理解为什么它给出输出adfrht 6,正确的输出是sadfrhty 8。

2 个答案:

答案 0 :(得分:4)

你得到错误结果的原因是因为基本方法缺少一些移动的部分。您没有跟踪计算此信息所需的所有信息。您不仅需要跟踪您所看到的字符,还要跟踪它们在字符串中的哪个位置(我认为您希望将其保持在O(n)复杂度)。

这样,当你看到之前遇到的一个字符时,你需要重置“到目前为止看到的连续非重复字符”计数器,以便在上一次出现相同字符后开始你在看当前的位置。此外,到目前为止所见到的所有角色,直到那一点,都不再被看到,因为如果你考虑它一秒钟,它应该对你有意义。

这是您实施中缺少的部分。此外,它没有跟踪最长字符串的位置,非常正确。

以下内容应该会产生您想要的结果。

告诉我们您的家庭作业所获得的成绩: - )

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <vector>

using namespace std;

int main()
{
    string s = "aaaaaaaaaaaaasadfrhtytbgrbrsvsrhvsg";
    vector<bool> v(256,false);
    vector<int> seen_at(256);

    int longest_starting_pos=0, longest_length=0;

    int current_length=0;

    for (int i=0; i<s.length(); i++)
    {
        if (v[s[i]])
        {
            for (int j=i-current_length; j<seen_at[s[i]]; ++j)
                v[s[j]]=false;
            current_length=i-seen_at[s[i]]-1;
        }

        v[s[i]]=true;
        seen_at[s[i]]=i;
        if (++current_length > longest_length)
        {
            longest_length=current_length;
            longest_starting_pos=i-current_length+1;
        }
    }

    cout<<s.substr(longest_starting_pos, longest_length)+" "<<longest_length<<endl;
}

答案 1 :(得分:0)

您的算法不正确。你的算法有什么问题,一旦它检查一个字符,如果包含该字符的子字符串不能最长,它就不会再返回该字符再次检查它。第一个s正在检查长度为2的字符串as,但是当找到下一个a时,s会被遗忘,即使它可能会下一个子串更长。试试这段代码:

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <vector>

using namespace std;

int main()
{
    string s = "aaaaaaaaaaaaasadfrhtytbgrbrsvsrhvsg";
    vector<bool> v(256,false);
    int longStart = 0;
    int longEnd = 0;
    int start = 0

    for (end = 0; end < s.length(); end++)
    {
        if (!v[s[end]])   // if character not already in the substring
        {
            v[s[end]] = true;

            if (end - start > longEnd - longStart)
            {
                longEnd = end;
                longStart = start;
            }
        }
        else   //the character is already in the substring, so increment the
               //start of the substring until that character is no longer in it
        {
            //get to the conflicting character, but don't get to the new character
            while ((s[start] != s[end]) && (start < end))
            {
                start++;
                v[s[start]] = false;
            }

            //remove the conflicting character
            start++;
            //don't set v[s[start]] to false because that character is still
            //encountered, but as the newly appended character, not the first
        }
    }

    longEnd++;    //make longEnd the index after the last character for substring purposes
    cout << s.substr(longStart, longEnd - longStart) + " " << (longEnd - longStart) << endl;
}

基本上这个代码的作用是保持一个正在运行的子字符串,每当它遇到一个已经在子字符串中的字符时,它会增加子字符串的开头,直到新字符不再在子字符串中,然后继续正常。如果该子串长于先前认为最长的子串,它还会在每次结束时检查。这是O(n)我相信你想要的。

此外,将代码传播出去。如果您无法读取并轻松调试,简洁代码就没有任何意义。此外,如果您的代码存在问题,请手动完成所有操作,以便更好地了解它的工作原理和发生的情况。

希望这有帮助!