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.

Updated on: 2026-03-26T18:22:20+05:30

387 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements