5 Best Ways to Check If Suffix and Prefix of a String Are Palindromes in Python

Rate this post

πŸ’‘ Problem Formulation: This article addresses the challenge of determining whether the prefixes and suffixes of a given string are palindromes in Python. Specifically, it considers strings where one may extract a prefix or suffix of any length and check its palindromic properties. For instance, given the input ‘racecar’, the desired output would confirm that ‘racecar’, ‘raceca’, ‘racec’, etc. are palindromic substrings at the prefix, and similarly ‘racecar’, ‘acecar’, ‘cecar’, etc. at the suffix.

Method 1: Iterative Approach

Employing an iterative approach, we manually compare character by character from both ends of a substring to check for palindrome properties. This method’s function, is_palindrome(), takes a string and verifies if it’s the same read forwards and backwards by iterating through each character.

Here’s an example:

def is_palindrome(s):
    for i in range(len(s) // 2):
        if s[i] != s[~i]:
            return False
    return True

def prefix_suffix_palindrome(string):
    for i in range(len(string), 0, -1):
        if is_palindrome(string[:i]) and is_palindrome(string[-i:]):
            print(f"Prefix & Suffix of length {i}: {string[:i]} - Palindrome!")

prefix_suffix_palindrome("racecar")

Output:

Prefix & Suffix of length 7: racecar - Palindrome!
Prefix & Suffix of length 3: rac - Palindrome!
Prefix & Suffix of length 1: r - Palindrome!

The is_palindrome() function iterates halfway through the string, checking if each character matches its counterpart from the other end. The prefix_suffix_palindrome() function then uses this helper to check for palindromes in decreasing lengths of the input string’s prefixes and suffixes, printing matched palindromes.

Method 2: Python Slicing

Simplifying the task with Python slicing syntax, one can reverse a substring and compare it to the original to confirm a palindrome. The slicing method [::-1] reverses the string, providing a quick means to compare the reversed and original strings.

Here’s an example:

def check_palindrome_substring(s):
    return s == s[::-1]

string = "racecar"
for i in range(len(string), 0, -1):
    if check_palindrome_substring(string[:i]) and check_palindrome_substring(string[-i:]):
        print(f"Prefix & Suffix of length {i}: {string[:i]} - Palindrome!")

Output:

Prefix & Suffix of length 7: racecar - Palindrome!
Prefix & Suffix of length 3: rac - Palindrome!
Prefix & Suffix of length 1: r - Palindrome!

This code defines check_palindrome_substring(), which returns True or False after comparing a string with its reversed version made through slicing. Looping over lengths of the input string, we check whether substrings formed as prefixes and suffixes are palindromes. Matches are printed out.

Method 3: Using Recursion

Recursive approaches offer an elegant way to solve palindromic checks. The recursive function reduces the problem size with each call by peeling off the ends of the string until the base cases are met. This method is very logical and potentially easier to understand from a computer science perspective.

Here’s an example:

def is_palindrome_recursive(string):
    if len(string) < 2: return True
    if string[0] != string[-1]: return False
    return is_palindrome_recursive(string[1:-1])

def prefix_suffix_palindrome_recursive(string):
    for i in range(len(string), 0, -1):
        if is_palindrome_recursive(string[:i]) and is_palindrome_recursive(string[-i:]):
            print(f"Prefix & Suffix of length {i}: {string[:i]} - Palindrome!")

prefix_suffix_palindrome_recursive("racecar")

Output:

Prefix & Suffix of length 7: racecar - Palindrome!
Prefix & Suffix of length 3: rac - Palindrome!
Prefix & Suffix of length 1: r - Palindrome!

Using the function is_palindrome_recursive(), this code checks if the first and last characters match and then recursively sends the substring excluding those characters back into the function. The main function, prefix_suffix_palindrome_recursive(), uses this technique to validate palindrome substrings at both ends of the input string.

Method 4: Using Python’s Built-in Functions

Capitalizing on Python’s standard library, specifically the all() function, allows for a more concise way to check each character in a string for palindromic patterns. It enhances readability and reduces the code needed for iteration.

Here’s an example:

def is_palindrome_builtin(s):
    return all(s[i] == s[~i] for i in range(len(s) // 2))

def prefix_suffix_palindrome_builtin(string):
    for i in range(len(string), 0, -1):
        if is_palindrome_builtin(string[:i]) and is_palindrome_builtin(string[-i:]):
            print(f"Prefix & Suffix of length {i}: {string[:i]} - Palindrome!")

prefix_suffix_palindrome_builtin("racecar")

Output:

Prefix & Suffix of length 7: racecar - Palindrome!
Prefix & Suffix of length 3: rac - Palindrome!
Prefix & Suffix of length 1: r - Palindrome!

This snippet defines is_palindrome_builtin(), using all() to iterate over half of the string and compare each character to its opposite. This approach is elegant and leverages Python’s ability to concisely express iteration with built-in functions.

Bonus One-Liner Method 5: List Comprehension with Slicing

A one-liner method demonstrating the power of Python’s list comprehensions combines slicing and conditional checks into a single line for ultra-compact code.

Here’s an example:

string = "racecar"
result = [(string[:i], string[-i:]) for i in range(len(string), 0, -1) if string[:i] == string[:i][::-1] and string[-i:] == string[-i:][::-1]]
print(result)

Output:

[('racecar', 'racecar'), ('rac', 'rac'), ('r', 'r')]

The code contains a list comprehension that goes over each length of the input string’s prefixes and suffixes and uses slicing to create reversed versions, which it directly compares. Matching pairs are added to the resulting list which is printed out.

Summary/Discussion

  • Method 1: Iterative Approach. Direct and explicit, offering clear control over the checking process. However, it may be less pythonic and more verbose compared to other methods.
  • Method 2: Python Slicing. Clean and idiomatic Python solution, very readable, but potentially less efficient due to string copying while reversing.
  • Method 3: Using Recursion. Elegant solution emphasizing a divide-and-conquer strategy, easy to understand from a computer science perspective. May not be as efficient for larger strings due to recursive call overhead.
  • Method 4: Using Python’s Built-in Functions. Enhanced readability through the use of all(), concise, yet carries the overhead of a lambda function over a direct comparison.
  • Bonus Method 5: List Comprehension with Slicing. Offers a one-liner solution, showcasing Python’s ability to condense logic but may be less readable to newcomers.