I answered rather early in the comments to your question (the 3rd comment) that you could use the approach with comparing "lol" with a substring of the big string to evaluate. Using the "substr" function.
Somebody else proposed the "find" function. Then you said in the 5th comment:
this task without using any built in function @JohnnyMopp sorry i should tell that in my question
So then, we should use the fully handcrafted so called "naive sliding window" approach. This is very simple to understand and for your use case completely sufficient.
I will first give a detailed explanation and then implement this idea in a simple approach with a simple programming style.
It will work without using any built in function, so it will be completely based on standard instructions.
How does this work?
You iterate over the search string and then move a sliding window over it. The Window length is the size of the string to be found.
Normally, the window would simply be defined by a substr
function, but, because you said that you do not want to have a function, we will use a 2nd loop. This will not slow down your program in any noticable way here.
Example:
str2 abclololdef
window | |
window content abc Now compare window with str1
slide 1 to the right:
str2 abclololdef
window | |
window content bcl Now compare window with str1
slide 1 to the right:
str2 abclololdef
window | |
window content clo Now compare window with str1
slide 1 to the right:
str2 abclololdef
window | |
window content lol Now compare window with str1. Found. Increment counter
slide 1 to the right:
str2 abclololdef
window | |
window content olo Now compare window with str1
slide 1 to the right:
str2 abclololdef
window | |
window content lol Now compare window with str1. Found. Increment counter
slide 1 to the right:
str2 abclololdef
window | |
window content old Now compare window with str1.
slide 1 to the right:
str2 abclololdef
window | |
window content lde Now compare window with str1.
slide 1 to the right:
str2 abclololdef
window | |
window content def Now compare window with str1.
Now, window is at end. Stop sliding.
You see. There is a window. The window has a start position and a width (the size of str1) and an end position which is "start position + width"
Care must be taken, that we do not slide the window over the right boundary of str1.
For the comparision we compare position 0 of "lol" with str2[startIndex], then position 1 of "lol" with str2[startIndex+1] and position 2 of "lol" with str2[startIndex+2]. This we will do in a small loop.
This can be translated 1 to 1 to code:
#include <iostream>
#include <string>
int main() {
// This is the string that we are looking for
std::string stringToFind = "lol";
// Get string to evaluate from user
std::string stringToEvaluate{};
std::cin >> stringToEvaluate;
// The width of length of the window
int width = stringToFind.length();
// Here we will store the number of times we find "lol"
int counter = 0;
// Now iterate over the complete input string. Do NOT cross boundaries
for (int k = 0; k < stringToEvaluate.length() - width; ++k) {
// Define the sliding window position
int startPosition = k;
int endPosition = k + width;
int windowIndex = 0;
//Here we will store, if we have a full OK comparison; Assum OK in the beginning
bool allEqual = true;
// Now compare the window ketter with the lol string
for (int windowPositionIndex = startPosition; windowPositionIndex < endPosition; ++windowPositionIndex) {
// Compare window with base string
if (stringToEvaluate[windowPositionIndex] != stringToFind[windowIndex]) {
allEqual = false;
break;
}
// Next letter of the search string
++windowIndex;
}
if (allEqual) ++counter;
}
std::cout << counter << '\n';
}
Because of the ultra simple programming style with creating many intermediate variables with "speaking" names and by writing many comments, this should be somehow understandable (I hope)
EDIT
I saw in comments that people were discussing about speed and big O notation. And that we could use KMP with an O(n+m) complexity.
I can show an even faster solution, with O(n-3), and I will still work without using any built in function during execution.
The idea is taken from Rabin-Karp. But, we can observe that we do not need to calculate hash values. We can directly convert a 3byte string to an 32bit unsigned integer. And then make comparisons on integer basis. Mening, we will treat the string as an overlapping integer array. So, we will first create a compile time constant hash value for the string "lol" (7106412) and then do the complete comparison with the string "lol" with one "cmp edx, 7106412" assembler instruction.
We take also advantage of the fact that std::string
will be 0-terminated since C++11.
This will result in compact code (6 statements in main, inclusive output), outperforms everthing else in regards to speed and still works without using any built in function or library.
#include <iostream>
#include <string>
// Hash for the string that we are looking for
constexpr unsigned int hash = ('l' << 16) + ('o' << 8) + 'l';
// or: const unsigned int hash = *reinterpret_cast<const unsigned int*>("lol");
int main() {
// Take any test string to evaluate
std::string stringToEvaluate{ "aaaaalololbbbbbllpolcccccllollddddd" };
// Here we will store the number of times we find "lol"
unsigned int counter = 0;
// Now iterate over the input string. Do not cross boundaries
for (size_t k = 0; k < stringToEvaluate.length() - 3; ++k) {
// Compare hash values
if (hash == (*reinterpret_cast<unsigned int*>(&stringToEvaluate[k])) >> 8)
++counter;
}
std::cout << counter << '\n';
}
Compiled and tested with Microsoft Visual Studio Community 2019, Version 16.11.0 and gcc11.2 and Clang13 with "-O3 -Werror -Wall -Wpedantic"