object NonOverlappingCount {
// Non‑overlapping occurrences are matches of a substring that do not reuse any of
// the same characters. Once one match is counted, the next search must begin
// after that match ends.
def countNonOverlapping(haystack: String, needle: String): Int = {
/*
Count how many times 'needle' appears in 'haystack' without overlapping.
The algorithm:
• Use .indexOf() to locate the next occurrence.
• Each time a match is found, move the search index forward
by the full length of the matched substring.
• This ensures no characters are reused between matches.
*/
var count = 0
var index = 0 // current search position in the main string
// Continue searching until .indexOf() returns -1 (meaning: no more matches)
while ({
// Find the next occurrence starting at the current index
val pos = haystack.indexOf(needle, index)
if (pos == -1) {
// No more matches found
false
} else {
// We found a match, so increment the count
count += 1
// Move index forward by the length of the needle
// This ensures the next search begins *after* the matched substring
index = pos + needle.length
true
}
}) ()
count
}
// ---------------------------------------------------------------
def main(args: Array[String]): Unit = {
val s = "go java phphp rust c pphpp c++ phpphp python php phphp"
val substring = "php"
// Count non-overlapping occurrences
val result = countNonOverlapping(s, substring)
println(s"Non-overlapping occurrences: $result")
}
}
/*
run:
Non-overlapping occurrences: 6
*/