Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Find all palindromic sub-strings of a given string - Set 2 in Python
A palindrome is a string that reads the same forwards and backwards. Finding all palindromic sub-strings involves checking every possible substring. This implementation uses the expand around centers approach with fractional positions to handle both odd and even-length palindromes efficiently.
How the Algorithm Works
The algorithm uses fractional positions (0.0, 0.5, 1.0, 1.5...) to represent centers:
- Integer positions (0, 1, 2...) represent centers of odd-length palindromes
- Half positions (0.5, 1.5, 2.5...) represent centers of even-length palindromes
- For each center, expand outward while characters match
Implementation
Here's the complete solution that finds all palindromic substrings ?
def get_all_pal_sub(s):
palindromes = []
pos = 0.0
while pos < len(s):
# Calculate radius from center
rad = pos - int(pos)
# Expand around center while characters match
while ((pos + rad) < len(s) and
(pos - rad) >= 0 and
(s[int(pos - rad)] == s[int(pos + rad)])):
# Extract palindromic substring
start = int(pos - rad)
end = int(pos + rad + 1)
palindromes.append(s[start:end])
rad += 1
# Move to next center (half step for even/odd coverage)
pos += 0.5
return palindromes
# Test with example
text = "redivider"
result = get_all_pal_sub(text)
print(f"Found {len(result)} palindromes:")
print(result)
The output of the above code is ?
Found 13 palindromes: ['r', 'e', 'd', 'i', 'v', 'ivi', 'divid', 'edivide', 'redivider', 'i', 'd', 'e', 'r']
Step-by-Step Breakdown
Let's trace through how the algorithm processes "aba" ?
def trace_palindromes(s):
palindromes = []
pos = 0.0
print(f"Processing string: '{s}'")
print("Position | Center Type | Palindromes Found")
print("-" * 45)
while pos < len(s):
rad = pos - int(pos)
center_type = "odd" if rad == 0 else "even"
found_at_pos = []
while ((pos + rad) < len(s) and
(pos - rad) >= 0 and
(s[int(pos - rad)] == s[int(pos + rad)])):
palindrome = s[int(pos - rad):int(pos + rad + 1)]
palindromes.append(palindrome)
found_at_pos.append(palindrome)
rad += 1
print(f"{pos:8.1f} | {center_type:11} | {found_at_pos}")
pos += 0.5
return palindromes
# Trace example
result = trace_palindromes("aba")
The output shows the algorithm's process ?
Processing string: 'aba'
Position | Center Type | Palindromes Found
---------------------------------------------
0.0 | odd | ['a']
0.5 | even | []
1.0 | odd | ['b', 'aba']
1.5 | even | []
2.0 | odd | ['a']
Why Fractional Positions Work
Using fractional positions elegantly handles both palindrome types ?
# Example showing odd vs even palindrome detection
def demonstrate_centers():
s = "abccba"
print("String:", s)
print("Indices: 0 1 2 3 4 5")
print()
# Odd-length palindrome centered at position 2.5
print("Even-length palindrome 'cc' centered at position 2.5:")
print("Left char at index 2, right char at index 3")
# Odd-length palindrome centered at position 3
print("\nOdd-length palindrome 'bccb' centered at position 3:")
print("Expands from center character 'c' at index 3")
demonstrate_centers()
String: abccba Indices: 0 1 2 3 4 5 Even-length palindrome 'cc' centered at position 2.5: Left char at index 2, right char at index 3 Odd-length palindrome 'bccb' centered at position 3: Expands from center character 'c' at index 3
Comparison with Brute Force
| Method | Time Complexity | Space Complexity | Approach |
|---|---|---|---|
| Brute Force | O(n³) | O(1) | Check all substrings |
| Expand Centers | O(n²) | O(1) | Expand from each center |
| Manacher's | O(n) | O(n) | Linear time algorithm |
Conclusion
The expand-around-centers algorithm with fractional positions efficiently finds all palindromic substrings in O(n²) time. The fractional position technique elegantly handles both odd and even-length palindromes in a single pass.
