Boundary update without `+1` / `-1`
Wrong move: Setting `lo = mid` or `hi = mid` can stall and create an infinite loop.
Usually fails on: Two-element ranges never converge.
Fix: Use `lo = mid + 1` or `hi = mid - 1` where appropriate.
Break down a hard problem into reliable checkpoints, edge-case handling, and complexity trade-offs.
You are building a string s of length n one character at a time, prepending each new character to the front of the string. The strings are labeled from 1 to n, where the string with length i is labeled si.
s = "abaca", s1 == "a", s2 == "ca", s3 == "aca", etc.The score of si is the length of the longest common prefix between si and sn (Note that s == sn).
Given the final string s, return the sum of the score of every si.
Example 1:
Input: s = "babab" Output: 9 Explanation: For s1 == "b", the longest common prefix is "b" which has a score of 1. For s2 == "ab", there is no common prefix so the score is 0. For s3 == "bab", the longest common prefix is "bab" which has a score of 3. For s4 == "abab", there is no common prefix so the score is 0. For s5 == "babab", the longest common prefix is "babab" which has a score of 5. The sum of the scores is 1 + 0 + 3 + 0 + 5 = 9, so we return 9.
Example 2:
Input: s = "azbazbzaz" Output: 14 Explanation: For s2 == "az", the longest common prefix is "az" which has a score of 2. For s6 == "azbzaz", the longest common prefix is "azb" which has a score of 3. For s9 == "azbazbzaz", the longest common prefix is "azbazbzaz" which has a score of 9. For all other si, the score is 0. The sum of the scores is 2 + 3 + 9 = 14, so we return 14.
Constraints:
1 <= s.length <= 105s consists of lowercase English letters.Problem summary: You are building a string s of length n one character at a time, prepending each new character to the front of the string. The strings are labeled from 1 to n, where the string with length i is labeled si. For example, for s = "abaca", s1 == "a", s2 == "ca", s3 == "aca", etc. The score of si is the length of the longest common prefix between si and sn (Note that s == sn). Given the final string s, return the sum of the score of every si.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Binary Search · String Matching
"babab"
"azbazbzaz"
longest-happy-prefix)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #2223: Sum of Scores of Built Strings
class Solution {
public long sumScores(String s) {
final int n = s.length();
// https://cp-algorithms.com/string/z-function.html#implementation
int[] z = new int[n];
// [l, r] := the indices of the rightmost segment match
int l = 0;
int r = 0;
for (int i = 1; i < n; ++i) {
if (i < r)
z[i] = Math.min(r - i, z[i - l]);
while (i + z[i] < n && s.charAt(z[i]) == s.charAt(i + z[i]))
++z[i];
if (i + z[i] > r) {
l = i;
r = i + z[i];
}
}
return Arrays.stream(z).asLongStream().sum() + n;
}
}
// Accepted solution for LeetCode #2223: Sum of Scores of Built Strings
// Auto-generated Go example from java.
func exampleSolution() {
}
// Reference (java):
// // Accepted solution for LeetCode #2223: Sum of Scores of Built Strings
// class Solution {
// public long sumScores(String s) {
// final int n = s.length();
// // https://cp-algorithms.com/string/z-function.html#implementation
// int[] z = new int[n];
// // [l, r] := the indices of the rightmost segment match
// int l = 0;
// int r = 0;
//
// for (int i = 1; i < n; ++i) {
// if (i < r)
// z[i] = Math.min(r - i, z[i - l]);
// while (i + z[i] < n && s.charAt(z[i]) == s.charAt(i + z[i]))
// ++z[i];
// if (i + z[i] > r) {
// l = i;
// r = i + z[i];
// }
// }
//
// return Arrays.stream(z).asLongStream().sum() + n;
// }
// }
# Accepted solution for LeetCode #2223: Sum of Scores of Built Strings
class Solution:
def sumScores(self, s: str) -> int:
n = len(s)
# https://cp-algorithms.com/string/z-function.html#implementation
z = [0] * n
# [l, r] := the indices of the rightmost segment match
l = 0
r = 0
for i in range(1, n):
if i < r:
z[i] = min(r - i, z[i - l])
while i + z[i] < n and s[z[i]] == s[i + z[i]]:
z[i] += 1
if i + z[i] > r:
l = i
r = i + z[i]
return sum(z) + n
// Accepted solution for LeetCode #2223: Sum of Scores of Built Strings
/**
* [2223] Sum of Scores of Built Strings
*
* You are building a string s of length n one character at a time, prepending each new character to the front of the string. The strings are labeled from 1 to n, where the string with length i is labeled si.
*
* For example, for s = "abaca", s1 == "a", s2 == "ca", s3 == "aca", etc.
*
* The score of si is the length of the longest common prefix between si and sn (Note that s == sn).
* Given the final string s, return the sum of the score of every si.
*
* Example 1:
*
* Input: s = "babab"
* Output: 9
* Explanation:
* For s1 == "b", the longest common prefix is "b" which has a score of 1.
* For s2 == "ab", there is no common prefix so the score is 0.
* For s3 == "bab", the longest common prefix is "bab" which has a score of 3.
* For s4 == "abab", there is no common prefix so the score is 0.
* For s5 == "babab", the longest common prefix is "babab" which has a score of 5.
* The sum of the scores is 1 + 0 + 3 + 0 + 5 = 9, so we return 9.
* Example 2:
*
* Input: s = "azbazbzaz"
* Output: 14
* Explanation:
* For s2 == "az", the longest common prefix is "az" which has a score of 2.
* For s6 == "azbzaz", the longest common prefix is "azb" which has a score of 3.
* For s9 == "azbazbzaz", the longest common prefix is "azbazbzaz" which has a score of 9.
* For all other si, the score is 0.
* The sum of the scores is 2 + 3 + 9 = 14, so we return 14.
*
*
* Constraints:
*
* 1 <= s.length <= 10^5
* s consists of lowercase English letters.
*
*/
pub struct Solution {}
// problem: https://leetcode.com/problems/sum-of-scores-of-built-strings/
// discuss: https://leetcode.com/problems/sum-of-scores-of-built-strings/discuss/?currentPage=1&orderBy=most_votes&query=
// submission codes start here
impl Solution {
pub fn sum_scores(s: String) -> i64 {
0
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[ignore]
fn test_2223_example_1() {
let s = "babab".to_string();
let result = 9;
assert_eq!(Solution::sum_scores(s), result);
}
#[test]
#[ignore]
fn test_2223_example_2() {
let s = "azbazbzaz".to_string();
let result = 14;
assert_eq!(Solution::sum_scores(s), result);
}
}
// Accepted solution for LeetCode #2223: Sum of Scores of Built Strings
// Auto-generated TypeScript example from java.
function exampleSolution(): void {
}
// Reference (java):
// // Accepted solution for LeetCode #2223: Sum of Scores of Built Strings
// class Solution {
// public long sumScores(String s) {
// final int n = s.length();
// // https://cp-algorithms.com/string/z-function.html#implementation
// int[] z = new int[n];
// // [l, r] := the indices of the rightmost segment match
// int l = 0;
// int r = 0;
//
// for (int i = 1; i < n; ++i) {
// if (i < r)
// z[i] = Math.min(r - i, z[i - l]);
// while (i + z[i] < n && s.charAt(z[i]) == s.charAt(i + z[i]))
// ++z[i];
// if (i + z[i] > r) {
// l = i;
// r = i + z[i];
// }
// }
//
// return Arrays.stream(z).asLongStream().sum() + n;
// }
// }
Use this to step through a reusable interview workflow for this problem.
Check every element from left to right until we find the target or exhaust the array. Each comparison is O(1), and we may visit all n elements, giving O(n). No extra space needed.
Each comparison eliminates half the remaining search space. After k comparisons, the space is n/2ᵏ. We stop when the space is 1, so k = log₂ n. No extra memory needed — just two pointers (lo, hi).
Review these before coding to avoid predictable interview regressions.
Wrong move: Setting `lo = mid` or `hi = mid` can stall and create an infinite loop.
Usually fails on: Two-element ranges never converge.
Fix: Use `lo = mid + 1` or `hi = mid - 1` where appropriate.