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
Program to find n length string made of letters from m sized alphabet with no palindrome in Python
Given m letters and a value n, we need to count strings of length n that contain no palindromic substrings of length greater than 1. A palindromic substring reads the same forwards and backwards, like "aa" or "aba".
The key insight is that to avoid palindromes, no two adjacent characters can be the same, and no character at position i can equal the character at position i+2.
Algorithm
We follow these steps:
- If n = 1: Any single character is valid, so return m
- If n = 2: First character has m choices, second has m-1 choices (can't equal first)
- If m ? 2 and n > 2: Impossible to avoid palindromes with so few letters
- For n > 2: First character has m choices, second has m-1 choices, remaining positions each have m-2 choices
Example
Let's trace through n = 2, m = 3 with alphabet {x, y, z}:
def solve(n, m):
p = 10**9 + 7
if n == 1:
return m % p
if n == 2:
return m * (m - 1) % p
if m <= 2:
return 0
return m * (m - 1) * pow(m - 2, n - 2, p) % p
# Test case: n = 2, m = 3
n = 2
m = 3
result = solve(n, m)
print(f"For n={n}, m={m}: {result}")
# All possible 2-length strings from {x,y,z}
print("Valid strings: xy, xz, yx, yz, zx, zy")
print("Invalid strings: xx, yy, zz (palindromes)")
For n=2, m=3: 6 Valid strings: xy, xz, yx, yz, zx, zy Invalid strings: xx, yy, zz (palindromes)
Complete Implementation
def solve(n, m):
"""
Count n-length strings from m-letter alphabet with no palindromic substrings
"""
p = 10**9 + 7
# Single character - all are valid
if n == 1:
return m % p
# Two characters - second can't equal first
if n == 2:
return m * (m - 1) % p
# Need at least 3 different letters for longer strings
if m <= 2:
return 0
# For n > 2: first char has m choices, second has (m-1), rest have (m-2)
return m * (m - 1) * pow(m - 2, n - 2, p) % p
# Test different cases
test_cases = [(1, 3), (2, 3), (3, 3), (4, 3), (3, 2)]
for n, m in test_cases:
result = solve(n, m)
print(f"n={n}, m={m}: {result}")
n=1, m=3: 3 n=2, m=3: 6 n=3, m=3: 6 n=4, m=3: 6 n=3, m=2: 0
Why This Works
For strings longer than 2 characters, each position after the second must avoid:
- The previous character (to avoid "aa" pattern)
- The character two positions back (to avoid "aba" pattern)
This leaves exactly m-2 valid choices for each remaining position, giving us the formula: m × (m-1) × (m-2)^(n-2).
Conclusion
This algorithm efficiently counts non-palindromic strings using mathematical analysis rather than generating all possibilities. The time complexity is O(log n) due to the modular exponentiation.
