Skip to content

S1Q2 · Check String Rotation

⚡ Quick Reference

Function: is_rotation(str1: str, str2: str) -> bool

Core idea: every rotation of str1 appears as a substring of str1 + str1.

def is_rotation(str1: str, str2: str) -> bool:
    if len(str1) != len(str2):
        return False
    return str2 in str1 + str1

Key rules: - Lengths must match - a rotation never changes length - str2 in str1 + str1 checks if str2 is any rotation of str1 - This is an O(n) check - no loops needed


Problem Statement

Problem

Write a function is_rotation(str1, str2) that returns True if str2 is a rotation of str1, and False otherwise.

Examples:

Input
str1='abcde', str2='cdeab'
Output
True
Input
str1='hello', str2='ehllo'
Output
False
Input
str1='hello', str2='helol'
Output
False

The key insight - double concatenation

A rotation takes some characters from the front of str1 and moves them to the back. Every possible rotation of str1 is guaranteed to appear as a contiguous substring inside str1 + str1.

For str1 = "apple":

str1 + str1 = "appleapple"

Rotations hidden inside:
  a[pplea]pple  →  "pplea"
  ap[pleap]ple  →  "pleap"
  app[leapp]le  →  "leapp"
  appl[eappl]e  →  "eappl"
  apple[apple]  →  "apple"

So to check if str2 is a rotation: just check str2 in str1 + str1.

Why this works

If str2 is a rotation of str1, there exists some split point k such that: str2 = str1[k:] + str1[:k]

In str1 + str1, the substring starting at position k and running for len(str1) characters is exactly str1[k:] + str1[:k] = str2. So str2 is always found inside the doubled string.


Length check - why it matters

'ab' in 'abcdabcd' is True, but 'ab' is not a rotation of 'abcd' - it's just a shorter string. Always check lengths match first:

if len(str1) != len(str2):
    return False

Tracing all three examples

is_rotation('abcde', 'cdeab')

len match: 5 == 5 
str1 + str1 = "abcdeabcde"
'cdeab' in "abcdeabcde"?  → YES (positions 2–6)
→ True 

is_rotation('hello', 'ehllo')

len match: 5 == 5 
str1 + str1 = "hellohello"
'ehllo' in "hellohello"?  → NO
→ False 

is_rotation('hello', 'helol')

len match: 5 == 5 
str1 + str1 = "hellohello"
'helol' in "hellohello"?  → NO
→ False 


Solution approaches

def is_rotation(str1: str, str2: str) -> bool:
    if len(str1) != len(str2):
        return False
    return str2 in str1 + str1
def is_rotation(str1: str, str2: str) -> bool:
    if len(str1) != len(str2):
        return False
    doubled = str1 + str1       # contains all rotations
    return str2 in doubled
def is_rotation(str1: str, str2: str) -> bool:
    if len(str1) != len(str2):
        return False
    n = len(str1)
    for k in range(n):
        rotation = str1[k:] + str1[:k]
        if rotation == str2:
            return True
    return False

Explicitly generate every rotation and compare. Correct but O(n²) - much slower than the in approach for large strings. Good for understanding what a rotation is, not for production code.


Key takeaways

01

str2 in str1 + str1

The classic O(n) rotation check. Doubling the string contains every possible rotation as a substring. Memorise this trick - it comes up frequently.

02

Always check length first

A rotation never changes the length of a string. If lengths differ, return False immediately - no substring check needed. This also prevents false positives.

03

in operator for substring check

s2 in s1 checks if s2 is a contiguous substring of s1. It runs in O(n) using Python's built-in string search - no manual loop needed.