02. Maximise String Score
β GFG solution to the Maximise String Score problem: find maximum score by performing valid character jumps using dynamic programming and prefix sum optimization. π
The problem can be found at the following link: π Question Link
π§© Problem Description
You are given a string s, and a list of jumps[][] of size n, where each jumps[i] = [s1, s2] denotes that you are allowed to jump from character s1 to s2 in the forward direction.
Additionally, you are allowed to jump forward from a character to any other occurrence of the same character within the string.
You start at index 0 of the string. After every valid jump from index i to index j, where s[i] = s1 and s[j] = s2, you earn a score equal to the sum of ASCII values of all characters between the jump except for the characters equals s2, i.e.
score(i, j) = sum(ascii(s[k]) for i β€ k < j and s[k] != s[j]).
Determine the maximum score that can be achieved by performing a sequence of valid jumps starting from index 0.
π Examples
Example 1
Input: s = "forgfg", jumps[][] = [['f', 'r'], ['r', 'g']]
Output: 429
Explanation: We can jump from 'f' to 'r' at index 2, this will give a score equals to sum of ASCII value of 'f', 'o' i.e. 213.
Now we can jump from 'r' to 'g' at index 5, this will give a score equals to sum of ASCII value of 'r', 'f' i.e. 216.
Hence maximum total score obtained will be 429.Example 2
Input: s = "abcda", jumps[][] = [['b', 'd']]
Output: 297
Explanation: We can jump from 'a' to 'a' (as both are same character) at index 4, this will give a score equals to sum of ASCII value of 'b', 'c', 'd' i.e. 297.
Hence maximum total score obtained will be 297.π Constraints
$1 \le |s| \le 2 \times 10^5$
$1 \le \text{jumps.size()} \le 676$
There are at least two distinct characters in s.
β
My Approach
The optimal approach uses Dynamic Programming with Prefix Sum Optimization and Precomputed Next Character Positions:
Dynamic Programming + Prefix Sum
Initialize Jump Graph:
Add self-loops for all characters (a-z) to allow jumping to same character.
Build adjacency list storing which characters can be jumped to from each character.
Precompute Next Character Positions:
Create a 2D array
nxt[i][c]storing the next occurrence index of charactercafter positioni.Process string from right to left, maintaining last seen position of each character.
Compute Prefix Sums:
Build prefix sum array of ASCII values for O(1) range sum queries.
pre[i]stores sum of ASCII values from index 0 to i-1.
Dynamic Programming:
dp[i]represents maximum score achievable starting from indexi.Process positions from right to left (n-2 to 0).
For each position, try all valid jumps from current character.
Calculate score:
pre[j] - pre[i + offset] + dp[j], where offset is 1 if jumping to same character.
Return Result:
Maximum score starting from index 0 is stored in
dp[0].
π Time and Auxiliary Space Complexity
Expected Time Complexity: O(n Γ m), where n is the length of the string and m is the average number of valid jumps per character. Each position is processed once, and for each position we iterate through all possible jumps (at most 26 + additional custom jumps). The precomputation of next positions takes O(n Γ 26) = O(n) time.
Expected Auxiliary Space Complexity: O(n + m), where n is used for storing DP array, prefix sum array, and next position matrix (n Γ 26), and m is for storing the jump graph adjacency list. The space is dominated by the O(n Γ 26) matrix for next positions.
π§βπ» Code (C++)
class Solution {
public:
int maxScore(string &s, vector<vector<char>> &jumps) {
int n = s.size();
for (char c = 'a'; c <= 'z'; c++) jumps.push_back({c, c});
vector<vector<int>> nxt(n, vector<int>(26, -1));
vector<int> last(26, -1);
for (int i = n - 1; i >= 0; i--) {
nxt[i] = last;
last[s[i] - 'a'] = i;
}
vector<vector<int>> ch(26);
for (auto &j : jumps) ch[j[0] - 'a'].push_back(j[1]);
vector<int> pre(n + 1);
for (int i = 0; i < n; i++) pre[i + 1] = pre[i] + s[i];
vector<int> dp(n);
for (int i = n - 2; i >= 0; i--) {
for (int c : ch[s[i] - 'a']) {
int j = nxt[i][c - 'a'];
if (j != -1) dp[i] = max(dp[i], pre[j] - pre[i + (c == s[i])] + dp[j]);
}
}
return dp[0];
}
};β Code (Java)
class Solution {
public int maxScore(String s, char[][] jumps) {
int n = s.length();
List<char[]> j = new ArrayList<>();
for (char[] x : jumps) j.add(x);
for (char c = 'a'; c <= 'z'; c++) j.add(new char[]{c, c});
int[][] nxt = new int[n][26];
int[] last = new int[26];
Arrays.fill(last, -1);
for (int i = n - 1; i >= 0; i--) {
System.arraycopy(last, 0, nxt[i], 0, 26);
last[s.charAt(i) - 'a'] = i;
}
List<List<Integer>> ch = new ArrayList<>();
for (int i = 0; i < 26; i++) ch.add(new ArrayList<>());
for (char[] x : j) ch.get(x[0] - 'a').add((int)x[1]);
int[] pre = new int[n + 1];
for (int i = 0; i < n; i++) pre[i + 1] = pre[i] + s.charAt(i);
int[] dp = new int[n];
for (int i = n - 2; i >= 0; i--) {
for (int c : ch.get(s.charAt(i) - 'a')) {
int k = nxt[i][c - 'a'];
if (k != -1) dp[i] = Math.max(dp[i], pre[k] - pre[i + (c == s.charAt(i) ? 1 : 0)] + dp[k]);
}
}
return dp[0];
}
}π Code (Python)
class Solution:
def maxScore(self, s, jumps):
n = len(s)
jumps += [[chr(c), chr(c)] for c in range(97, 123)]
nxt = [[-1] * 26 for _ in range(n)]
last = [-1] * 26
for i in range(n - 1, -1, -1):
nxt[i] = last[:]
last[ord(s[i]) - 97] = i
ch = [[] for _ in range(26)]
for u, v in jumps:
ch[ord(u) - 97].append(ord(v))
pre = [0] * (n + 1)
for i in range(n):
pre[i + 1] = pre[i] + ord(s[i])
dp = [0] * n
for i in range(n - 2, -1, -1):
for c in ch[ord(s[i]) - 97]:
j = nxt[i][c - 97]
if j != -1:
dp[i] = max(dp[i], pre[j] - pre[i + (c == ord(s[i]))] + dp[j])
return dp[0]π§ Contribution and Support
For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: π¬ Any Questions?. Let's make this learning journey more collaborative!
β If you find this helpful, please give this repository a star! β
πVisitor Count
Last updated