Program to Find Out the Strings of the Same Size in Python

In Python, we can solve the problem of finding strings of the same size with specific constraints using dynamic programming with memoization. Given a string and a maximum allowed consecutive character count, we need to find how many strings are lexicographically smaller or equal to the input string while satisfying the consecutive character limit.

Problem Understanding

Given a string s of lowercase letters and an integer k, we need to count strings that:

  • Have the same length as s

  • Are lexicographically smaller than or equal to s

  • Have no more than k consecutive equal characters

Algorithm Approach

We'll use dynamic programming with the following parameters:

  • pos − current position in the string

  • bound − whether we're still bounded by the original string

  • last − the last character we placed

  • count − current count of consecutive characters

Implementation

class Solution:
    def solve(self, s, k):
        if k <= 0:
            return 0
        
        MOD = 10 ** 9 + 7
        n = len(s)
        nums = [ord(char) - ord("a") for char in s]
        
        # Memoization cache
        cache = {}
        
        def dp(pos, bound, last, count):
            # If consecutive count exceeds k, invalid path
            if count > k:
                return 0
            
            # If we've built a complete string, it's valid
            if pos == n:
                return 1
            
            # Check cache
            state = (pos, bound, last, count)
            if state in cache:
                return cache[state]
            
            # Current character limit
            limit = nums[pos] + 1 if bound else 26
            result = 0
            
            # Try all possible characters
            for i in range(limit):
                new_count = count + 1 if i == last else 1
                new_bound = bound and (i == nums[pos])
                
                result += dp(pos + 1, new_bound, i, new_count)
                result %= MOD
            
            cache[state] = result
            return result
        
        return dp(0, True, -1, 0) % MOD

# Test the solution
ob = Solution()
result = ob.solve('app', 2)
print(f"Number of valid strings: {result}")
Number of valid strings: 405

How the Algorithm Works

The dynamic programming function works as follows:

  1. Base Cases: If consecutive count exceeds k, return 0. If we've built a complete string, return 1.

  2. Character Selection: For each position, try all valid characters (bounded by original string if still constrained).

  3. State Tracking: Track consecutive character count and whether we're still lexicographically bounded.

  4. Memoization: Cache results to avoid redundant calculations.

Example Walkthrough

For input string "app" with k=2:

# Test with different inputs
ob = Solution()

test_cases = [
    ("app", 2),
    ("abc", 1), 
    ("aa", 3)
]

for s, k in test_cases:
    result = ob.solve(s, k)
    print(f"String: '{s}', k: {k} ? Count: {result}")
String: 'app', k: 2 ? Count: 405
String: 'abc', k: 1 ? Count: 10
String: 'aa', k: 3 ? Count: 51

Conclusion

This dynamic programming solution efficiently counts valid strings by exploring all possibilities while respecting lexicographic bounds and consecutive character constraints. The memoization ensures optimal performance by avoiding redundant computations.

---
Updated on: 2026-03-25T13:55:58+05:30

201 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements