我正在尝试找到没有重复字符的最长子字符串。 我有一个布尔矢量来跟踪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。
答案 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)我相信你想要的。
此外,将代码传播出去。如果您无法读取并轻松调试,简洁代码就没有任何意义。此外,如果您的代码存在问题,请手动完成所有操作,以便更好地了解它的工作原理和发生的情况。
希望这有帮助!