AlgoMaster Logo

Repeated Substring Pattern

Last Updated: April 2, 2026

easy

Understanding the Problem

We need to determine if the entire string s is made up of some shorter substring repeated two or more times. So if s = "abab", the answer is true because "ab" repeated twice gives us "abab". But if s = "aba", there is no substring we can repeat to get the original string.

A few things to notice upfront. The repeating substring must divide the string evenly, meaning its length must be a divisor of the total string length. If the string has length 6, the candidate substring could have length 1, 2, or 3, but not 4 or 5. Also, the candidate substring length can be at most n/2 because we need at least two copies.

This divisibility constraint is what gives us a foothold. We do not need to try every possible substring, just the ones whose lengths divide n evenly.

Key Constraints:

  • 1 <= s.length <= 10^4 — With n up to 10,000, O(n^2) is feasible (100 million operations at worst). O(n * sqrt(n)) and O(n) are comfortable.
  • s consists of lowercase English letters — Standard character set, no special encoding concerns.

Approach 1: Brute Force (Check All Divisor Lengths)

Intuition

The most natural approach: try every possible substring length that could work, build the repeated string, and see if it matches the original.

Since the repeating unit must tile the entire string, its length has to divide n evenly. And we need at least two copies, so the maximum candidate length is n/2. For each valid candidate length len, we take the first len characters as our candidate substring, repeat it n/len times, and compare with s.

This is straightforward and easy to code correctly under interview pressure. For n up to 10^4, it runs fast enough.

Algorithm

  1. Get the length n of the string.
  2. For each candidate length len from 1 to n/2:

a. If n % len != 0, skip this length (it cannot tile the string evenly).

b. Build the candidate by repeating s[0..len-1] exactly n/len times.

c. If the built string equals s, return true.

  1. If no candidate length worked, return false.

Example Walkthrough

Input:

0
a
1
b
2
a
3
b
s

Try len=1: candidate "a", repeat 4 times = "aaaa" != "abab". Skip.

Try len=2: candidate "ab", repeat 2 times = "abab" == "abab". Match!

true
result

Code

This approach works but builds entirely new strings for each candidate length. What if we could detect repetition without constructing any new strings at all?

Approach 2: String Concatenation Trick

Intuition

Here is the elegant insight: if s is made of a repeating pattern, then when you concatenate s with itself to get s + s, the original s will appear somewhere in the middle of this doubled string (not just at the start and end positions).

Why? Say s = "abcabc". The repeating unit is "abc". When we form s + s = "abcabcabcabc", we get four copies of "abc" in a row. The original s appears starting at position 0 (trivially) and at position 6 (trivially), but it also appears starting at position 3 because positions 3-8 give us "abcabc".

Conversely, if s has no repeating pattern, then s only appears in s + s at positions 0 and n. Nowhere else.

So the algorithm is: form s + s, chop off the first and last characters (to eliminate the trivial matches at positions 0 and n), and check if s still appears in the result. If it does, the string has a repeating pattern.

Algorithm

  1. Concatenate s with itself to form doubled = s + s.
  2. Remove the first character and last character from doubled to get trimmed.
  3. If s is found as a substring within trimmed, return true.
  4. Otherwise, return false.

Example Walkthrough

1Start: s = "abab", form s + s = "abababab"
0
a
s (copy 1)
1
b
s (copy 1)
2
a
s (copy 1)
3
b
s (copy 1)
4
a
s (copy 2)
5
b
s (copy 2)
6
a
s (copy 2)
7
b
s (copy 2)
1/5

Code

The concatenation trick is elegant, but it relies on the language's built-in substring search. Can we detect the repeating pattern directly using the structure of the string itself?

Approach 3: KMP-Based (Failure Function)

Intuition

The KMP (Knuth-Morris-Pratt) algorithm's failure function reveals the internal repetitive structure of a string. The failure function for each position i stores the length of the longest proper prefix of s[0..i] that is also a suffix.

Here is the key insight: if a string of length n has a repeating pattern of length k, then the failure function value at the last position will be n - k. In other words, fail[n-1] = n - k. This means the string has a suffix of length n - k that matches a prefix of length n - k, and the remaining part (length k) is the repeating unit.

For this to represent a valid repeating pattern, k must divide n evenly. So the condition is: fail[n-1] > 0 (there is some prefix-suffix match) and n % (n - fail[n-1]) == 0 (the repeating unit length divides the string length).

Algorithm

  1. Build the KMP failure function array for the string s.
  2. Let failLast = fail[n-1], the failure function value at the last index.
  3. Compute the candidate pattern length: patternLen = n - failLast.
  4. If failLast > 0 and n % patternLen == 0, return true.
  5. Otherwise, return false.

Example Walkthrough

1Initialize: build failure function for s = "abcabcabc"
0
a
i=0
1
b
2
c
3
a
4
b
5
c
6
a
7
b
8
c
1/6
1Initialize failure function array with zeros
0
0
1
0
2
0
3
0
4
0
5
0
6
0
7
0
8
0
1/6

Code