In general, the indexing operation would depend on the way that the string is stored. In most cases, it is just a sequence of characters, each the same length, so indexing can be done in a single operation — hence, O(1) — by directly accessing the nth character.
However, in some cases, indexing may be more expensive; for example, some unicode strings can have characters of different sizes, in which case the only way to find character n is to start from the beginning and add up the individual character sizes, in which case it really is O(n).
All together, we then have to add n of those individual operations as we do for i in range(n)
, which gives another factor of n — note that this is the case even though for the second case it's O(1+2+3+4+...+n) which is O(n^2) since the sum is n*(n+1)/2. (In this case, you would probably use a somewhat different algorithm to still be able to perform this task in O(n), if efficiency is important.)