Reputation: 11
The aim of the function is to find out the longest and not repeating substring, so I need to find out the start position of the substring and the length of it. The thing I'm struggling with is the big O notation should be O(n). Therefore I cannot use nested for loops to check whether each letter is repeated. I created a struct function like this but I don't know how to continue:
struct Answer {
int start;
int length;
};
Answer findsubstring(char *string){
Answer sub={0, 0}
for (int i = 0; i < strlen(string); i++) {
}
return (sub)
}
For example, the input is HelloWorld
, and the output should be World
.The length is 5.
If the input isabagkfleoKi
, then the output is bagkfleoKi
. The length is 10.
Also, if the length of two strings is the same, pick the latter one.
Upvotes: 0
Views: 91
Reputation: 117258
I'll outline one possible solution.
auto stringlen = std::strlen(string);
for(size_t beg = 0; beg < stringlen - sub.length; ++beg) {
// See point 2.
for(size_t end = beg; end < stringlen; ++end) {
// See point 3.
}
}
bool blacklist[1 << CHAR_BIT]{}; // zero initialized
end
character is already in the blacklist
and break
out of the loop if it is, otherwise, put it in the blacklist.
if(blacklist[ static_cast<unsigned char>(string[end]) ]) break;
else {
blacklist[ static_cast<unsigned char>(string[end]) ] = true;
// See point 4.
}
end - beg + 1
) is greater than the longest you currently have (sub.length
). If it is longer, store sub.start = beg
and sub.length = end - beg + 1
Demo and Demo using a bitset<>
instead
Upvotes: 0
Reputation: 82461
Use a std::unordered_map<char, size_t>
to store the indices past the last occurance of a certain char.
Keep the currently best match as well as the match you currently test. Iterating through the chars of the input result in 2 cases you need to handle:
void printsubstring(const char* input)
{
std::unordered_map<char, size_t> lastOccurances;
Answer answer{ 0, 0 };
size_t currentPos = 0;
size_t currentStringStart = 0;
char c;
while ((c = input[currentPos]) != 0)
{
auto entry = lastOccurances.insert({ c, currentPos + 1 });
if (!entry.second)
{
if (currentStringStart < entry.first->second && currentPos - currentStringStart > answer.length)
{
// need to move the start of the potential answer
// -> check, if the match up to the char before the current char was better
answer.start = currentStringStart;
answer.length = currentPos - currentStringStart;
currentStringStart = entry.first->second;
}
entry.first->second = currentPos + 1;
}
++currentPos;
}
// check the match ending at the end of the string
if (currentPos - currentStringStart > answer.length)
{
answer.start = currentStringStart;
answer.length = currentPos - currentStringStart;
}
std::cout << answer.start << ", " << answer.length << std::endl;
std::cout << std::string_view(input + answer.start, answer.length) << std::endl;
}
Upvotes: 1