Find the minimum number of preprocess moves required to make two strings equal in Python

Given two strings P and Q of equal length containing only lowercase letters, we need to find the minimum number of preprocessing moves required to make them equal. A preprocessing move allows changing any character in string P to any other lowercase letter.

After preprocessing, we can apply these operations to make the strings equal:

  • Select any index i and swap characters P[i] and Q[i]

  • Select any index i and swap characters P[i] and P[n − i − 1]

  • Select any index i and swap characters Q[i] and Q[n − i − 1]

Note: The value of i is in range 0 ? i < n.

Algorithm Approach

The key insight is to process the strings in pairs from both ends. For each pair of positions (i, n−i−1), we analyze what characters are present and determine the minimum moves needed.

The algorithm works as follows:

  • For each pair of symmetric positions, count character frequencies

  • Based on the number of distinct characters, determine moves needed

  • Handle the middle character separately for odd−length strings

Example

Let's trace through an example with P = "pqprpqp" and Q = "qprpqpp":

def count_preprocess(P, Q):
    n = len(P)
    res = 0
    
    for i in range(n // 2):
        # Count frequency of characters at positions i and n-i-1
        char_count = {}
        
        # Add characters from P
        char_count[P[i]] = char_count.get(P[i], 0) + 1
        if P[i] != P[n - i - 1]:
            char_count[P[n - i - 1]] = char_count.get(P[n - i - 1], 0) + 1
        else:
            char_count[P[n - i - 1]] = char_count.get(P[n - i - 1], 0) + 1
            
        # Add characters from Q
        char_count[Q[i]] = char_count.get(Q[i], 0) + 1
        char_count[Q[n - i - 1]] = char_count.get(Q[n - i - 1], 0) + 1
        
        unique_chars = len(char_count)
        
        if unique_chars == 4:
            # All four characters are different - need 2 moves
            res += 2
        elif unique_chars == 3:
            # Three different characters - need 1 or 2 moves
            res += 1 + (P[i] == P[n - i - 1])
        elif unique_chars == 2:
            # Two different characters - might need 0 or 1 move
            res += (char_count[P[i]] != 2)
    
    # Handle middle character for odd-length strings
    if n % 2 == 1 and P[n // 2] != Q[n // 2]:
        res += 1
    
    return res

# Test with the example
P = "pqprpqp"
Q = "qprpqpp"
result = count_preprocess(P, Q)
print(f"Minimum preprocessing moves needed: {result}")
Minimum preprocessing moves needed: 4

How It Works

The algorithm analyzes each symmetric pair of positions and counts distinct characters:

  • 4 unique characters: Need 2 preprocessing moves to make swapping possible

  • 3 unique characters: Need 1−2 moves depending on whether P has matching characters at symmetric positions

  • 2 unique characters: May need 0−1 moves based on character distribution

  • 1 unique character: Already matching, no moves needed

Step−by−Step Trace

For P = "pqprpqp" and Q = "qprpqpp":

def trace_algorithm(P, Q):
    n = len(P)
    res = 0
    
    print(f"P = '{P}', Q = '{Q}'")
    print(f"Length: {n}")
    
    for i in range(n // 2):
        print(f"\nProcessing pair at positions {i} and {n-i-1}:")
        print(f"P[{i}] = '{P[i]}', P[{n-i-1}] = '{P[n-i-1]}'")
        print(f"Q[{i}] = '{Q[i]}', Q[{n-i-1}] = '{Q[n-i-1]}'")
        
        chars = [P[i], P[n-i-1], Q[i], Q[n-i-1]]
        unique_chars = len(set(chars))
        print(f"Characters: {chars}, Unique: {unique_chars}")
        
        if unique_chars == 4:
            moves = 2
        elif unique_chars == 3:
            moves = 1 + (P[i] == P[n-i-1])
        elif unique_chars == 2:
            char_count = {}
            for c in chars:
                char_count[c] = char_count.get(c, 0) + 1
            moves = (char_count[P[i]] != 2)
        else:
            moves = 0
            
        print(f"Moves needed for this pair: {moves}")
        res += moves
    
    # Handle middle character
    if n % 2 == 1:
        mid = n // 2
        if P[mid] != Q[mid]:
            print(f"\nMiddle character: P[{mid}] = '{P[mid]}', Q[{mid}] = '{Q[mid]}' - need 1 move")
            res += 1
    
    print(f"\nTotal moves needed: {res}")
    return res

trace_algorithm("pqprpqp", "qprpqpp")
P = 'pqprpqp', Q = 'qprpqpp'
Length: 7

Processing pair at positions 0 and 6:
P[0] = 'p', P[6] = 'p'
Q[0] = 'q', Q[6] = 'p'
Characters: ['p', 'p', 'q', 'p'], Unique: 2
Moves needed for this pair: 1

Processing pair at positions 1 and 5:
P[1] = 'q', P[5] = 'q'
Q[1] = 'p', Q[5] = 'p'
Characters: ['q', 'q', 'p', 'p'], Unique: 2
Moves needed for this pair: 0

Processing pair at positions 2 and 4:
P[2] = 'p', P[4] = 'p'
Q[2] = 'r', Q[4] = 'q'
Characters: ['p', 'p', 'r', 'q'], Unique: 3
Moves needed for this pair: 2

Middle character: P[3] = 'r', Q[3] = 'p' - need 1 move

Total moves needed: 4

Conclusion

This algorithm efficiently determines the minimum preprocessing moves by analyzing symmetric character pairs and their frequency distributions. The key insight is recognizing that certain character arrangements can be resolved through swapping operations, while others require preprocessing changes.

Updated on: 2026-03-25T09:34:24+05:30

336 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements