What's the ampersand on the right of the strings for?
They're references. Passing by const reference instead of by value avoids copies of the parameters being made. Aside from that, it doesn't change anything in this case.
Whats the string1.substr mean? And what are it's parameters?
I'm appending string3 to newString (see append()/operator+=).
assigning i to the length of string1 - 1
I'm adding it to i. This is necessary to skip the rest of the match. When "the" is found at the current position, I have to skip two more characters to avoid "he" being appended to the final string in the next two loop iterations. It's also necessary to avoid multiple substitutions when you have a string like "ssss" and want to replace "ss" with "Hello!". Without skipping, the result would be "Hello!Hello!Hello!s", even though only "Hello!Hello!" is correct.
the whole if else part is confusing to me.
To use the example input, I iterate over each character in "the dogs" and I append "those" when I find "the" at the current position, otherwise I just append the current character unchanged.
if string1.substr(starting from i, to the length of string 2, equals string2) ?
Yes.
also what does the size_t do?
size_t is an unsigned integral type for object sizes (usually 32/64 bit wide on the x86/x86_64 architectures) and corresponds to the type containers like std::string use for storing the number of elements. You could also use uint/int, however that type might not be wide enough to handle long strings on some platforms.