Difference between string += s1 and string = string + s1

std::string has members operator + and operator +=. The former is usually implemented with the latter by way of an intermediate temporary. Effectively looking something like this (check your implementation source if you want to know exactly what yours does):

/// note reference return type
std::string& operator +=(char c) 
    return *this;

// note value return type
std::string operator +(char c) const
    std::string tmp = *this;
    tmp += c; // or just tmp.append(c) directly
    return tmp;

The setup of tmp is expensive. The overall function can (and usually is) made better with move-assignment semantics to the final destination on the caller-side, but the expense of the temporary is none-the-less still there. Do it a few times and you won't notice the difference. Do it thousands, or millions, etc. of times, and it can mean a world of difference.

For built-in types a += b is exactly the same as a = a + b (except that a is evaluated only once), but for classes, those operators are overloaded and call different functions.
In your example fans = fans + s[i] creates a temporary string, and assigns (moves) it to fans, but fans += s[i] does not create that temporary, hence it may be faster.