AlgoMaster Logo

Rotate String

easyFrequency7 min readUpdated June 23, 2026

Understanding the Problem

We need to determine if one string is a rotation of another. A rotation means taking some number of characters from the front of the string and moving them to the back. For example, "cdeab" is a rotation of "abcde" because the first two characters ("ab") moved to the end.

If s and goal have different lengths, the answer is false. A string cannot rotate into a string of a different length, so this is an early exit before any real work.

The question that remains: given two strings of the same length, how do we check whether one is a rotation of the other?

Key Constraints:

  • 1 <= s.length, goal.length <= 100: With n capped at 100, even an O(n^2) scan over every rotation runs in at most 10,000 character comparisons. Runtime is not the concern here; the approaches differ mainly in how much extra memory they allocate and how cleanly they express the rotation idea.
  • s and goal consist of lowercase English letters. There are no special characters or unicode, so plain character-by-character comparison works.

Approach 1: Brute Force (Try All Rotations)

Intuition

Try every possible rotation of s and check whether any of them equals goal. A string of length n has at most n distinct rotations (including the original), so generating each one and comparing it against goal is enough to cover every case.

To generate the k-th rotation, take the substring from index k to the end and append the substring from index 0 to k. For "abcde" with k=2, that gives "cde" + "ab" = "cdeab".

Algorithm

  1. If s and goal have different lengths, return false.
  2. For each rotation amount k from 0 to n - 1:
    • Build the rotated string: s[k..n-1] + s[0..k-1].
    • If this equals goal, return true.
  3. If no rotation matches, return false.

Example Walkthrough

s
1k=0: rotation = "abcde", compare with goal "cdeab"
0
a
1
b
2
c
3
d
4
e
rotation k=0
goal
0
c
1
d
2
e
3
a
4
b
goal
1/6

Code

This rebuilds the entire string for every rotation. The next approach checks every rotation at once, without constructing each one separately.

Approach 2: Concatenate and Search

Intuition

Concatenating s with itself places every possible rotation of s as a contiguous substring inside s + s. For s = "abcde", s + s = "abcdeabcde" contains all five rotations as length-5 windows. The question becomes: is goal a substring of s + s?

Algorithm

  1. If s and goal have different lengths, return false.
  2. Concatenate s with itself to get doubled.
  3. Check if goal is a substring of doubled.
  4. If yes, return true. Otherwise, return false.

Example Walkthrough

s + s
1Step 1: Concatenate s with itself → "abcdeabcde"
0
a
1
b
2
c
3
d
4
e
first copy
5
a
6
b
7
c
8
d
9
e
second copy
goal
0
c
1
d
2
e
3
a
4
b
goal
1/6

Code

This is the shortest solution to write, but the built-in search has an O(n^2) worst case. The next approach makes the same concatenation idea O(n) by replacing the search with KMP.

Approach 3: Concatenation with KMP Search

Intuition

The concatenation idea from Approach 2 is correct: goal is a rotation of s exactly when goal is a substring of s + s (and the lengths match). The only weakness was the search itself, which the built-in methods run as a naive scan. The Knuth-Morris-Pratt (KMP) algorithm searches for a pattern inside a text in O(text + pattern) time, with no quadratic worst case.

Here goal is the pattern and s + s is the text. KMP precomputes a failure function (also called the longest-proper-prefix-suffix table) for goal. When a mismatch occurs partway through a match attempt, the failure function says how far the pattern can shift without rechecking characters already known to match, so the text pointer never moves backward. That is what removes the quadratic behavior.

Algorithm

  1. If s and goal have different lengths, return false.
  2. Build text = s + s and treat pattern = goal.
  3. Compute the failure table lps for pattern, where lps[i] is the length of the longest proper prefix of pattern[0..i] that is also a suffix of it.
  4. Scan text with KMP. Keep a pointer j into pattern. For each character of text:
    • While j > 0 and the characters mismatch, set j = lps[j - 1].
    • If they match, advance j.
    • If j reaches pattern.length, pattern was found, so return true.
  5. If the scan ends without j reaching pattern.length, return false.

Example Walkthrough

text = s + s
1i=0: text[0]='a' vs pattern[0]='c' -> mismatch, j stays 0
0
a
i=0
1
b
2
c
3
d
4
e
5
a
6
b
7
c
8
d
9
e
pattern = goal
0
c
j=0
1
d
2
e
3
a
4
b
1/8

Code