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 number of good ways to split a string using Python
Suppose we have a string s. A split is said to be a good split when we can split s into 2 non-empty strings p and q where their concatenation equals s and the number of distinct letters in p and q are equal. We need to find the number of good splits we can make in s.
For example, if the input is s = "xxzxyx", then the output will be 2. We can split it as ("xxz", "xyx") or ("xxzx", "yx") ? both are good splits since each part has the same number of distinct characters.
Algorithm
To solve this problem, we will follow these steps ?
Initialize
result = 0Create
leftas an empty counter for the left partCreate
rightcounter with frequency of each character in s-
For each character c in s:
Add c to left counter:
left[c] += 1Remove c from right counter:
right[c] -= 1If
right[c]becomes zero, delete it from right counterIf size of left equals size of right, increment result
Return result
Implementation
from collections import Counter
def solve(s):
result = 0
left, right = Counter(), Counter(s)
for c in s:
left[c] += 1
right[c] -= 1
if not right[c]:
del right[c]
if len(left) == len(right):
result += 1
return result
# Test the function
s = "xxzxyx"
print(f"String: {s}")
print(f"Number of good splits: {solve(s)}")
String: xxzxyx Number of good splits: 2
How It Works
Let's trace through the example "xxzxyx" step by step ?
from collections import Counter
def solve_with_trace(s):
result = 0
left, right = Counter(), Counter(s)
print(f"Initial right counter: {dict(right)}")
print()
for i, c in enumerate(s):
left[c] += 1
right[c] -= 1
if not right[c]:
del right[c]
print(f"After processing '{c}' at position {i}:")
print(f" Left part: '{s[:i+1]}' ? distinct chars: {len(left)}")
print(f" Right part: '{s[i+1:]}' ? distinct chars: {len(right)}")
if len(left) == len(right):
result += 1
print(f" ? Good split found! Total: {result}")
print()
return result
s = "xxzxyx"
solve_with_trace(s)
Initial right counter: {'x': 3, 'z': 1, 'y': 1}
After processing 'x' at position 0:
Left part: 'x' ? distinct chars: 1
Right part: 'xzxyx' ? distinct chars: 3
After processing 'x' at position 1:
Left part: 'xx' ? distinct chars: 1
Right part: 'zxyx' ? distinct chars: 3
After processing 'z' at position 2:
Left part: 'xxz' ? distinct chars: 2
Right part: 'xyx' ? distinct chars: 2
? Good split found! Total: 1
After processing 'x' at position 3:
Left part: 'xxzx' ? distinct chars: 2
Right part: 'yx' ? distinct chars: 2
? Good split found! Total: 2
After processing 'y' at position 4:
Left part: 'xxzxy' ? distinct chars: 3
Right part: 'x' ? distinct chars: 1
After processing 'x' at position 5:
Left part: 'xxzxyx' ? distinct chars: 3
Right part: '' ? distinct chars: 0
Key Points
We use two
Counterobjects to track character frequencies in left and right partsAs we iterate through the string, we move characters from right to left
We delete entries with zero count to get the correct distinct character count
A good split occurs when both parts have the same number of distinct characters
Conclusion
This algorithm efficiently finds good splits by maintaining frequency counters for both parts of the string. The time complexity is O(n) where n is the length of the string, making it an optimal solution for this problem.
