diff --git a/readme.md b/readme.md index 045e4eb..18e2097 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -## Algorithms (23/ 167) +## Algorithms (24/ 167) | Name | Tags | Solution | | --------------------------------------------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | @@ -16,7 +16,7 @@ | Making Anagrams | `Strings` | [TypeScript](./src/algorithms/strings/make-anagram) | | Alternating Characters | `Strings` | [TypeScript](./src/algorithms/strings/alternating-characters) | | Sherlock and the Valid String | `Strings` | [TypeScript](./src/algorithms/strings/sherlock-and-the-valid-string) | -| Special String Again | `Strings` | | +| Special String Again | `Strings` | [TypeScript](./src/algorithms/strings/special-string-again) | | Common Child | `Strings` | | | Contains-Duplicate | `Arrays`, `Hash Tables` | [TypeScript](./src/algorithms/arrays_hashtables/contains-duplicate) | | Valid Anagram | `Arrays`, `Hash Tables` | [TypeScript](./src/algorithms/arrays_hashtables/valid-anagram) | diff --git a/src/algorithms/strings/special-string-again/special-string-again.spec.ts b/src/algorithms/strings/special-string-again/special-string-again.spec.ts new file mode 100644 index 0000000..c15a4ef --- /dev/null +++ b/src/algorithms/strings/special-string-again/special-string-again.spec.ts @@ -0,0 +1,31 @@ +import { substrCount } from './special-string-again' + +describe('Special String Again', () => { + it('should handle single character string', () => { + expect(substrCount(1, 'a')).toBe(1) + }) + + it('should count all substrings when all characters are the same', () => { + expect(substrCount(4, 'aaaa')).toBe(10) + }) + + it('should count symmetrical substrings like aba', () => { + expect(substrCount(3, 'aba')).toBe(4) + }) + + it('should count a complex pattern', () => { + expect(substrCount(7, 'abcbaba')).toBe(10) + }) + + it('should handle empty string', () => { + expect(substrCount(0, '')).toBe(0) + }) + + it('should handle all different characters', () => { + expect(substrCount(5, 'abcde')).toBe(5) + }) + + it('should handle repeating and symmetric', () => { + expect(substrCount(8, 'aabbaabb')).toBe(12) + }) +}) diff --git a/src/algorithms/strings/special-string-again/special-string-again.ts b/src/algorithms/strings/special-string-again/special-string-again.ts new file mode 100644 index 0000000..6ea60d6 --- /dev/null +++ b/src/algorithms/strings/special-string-again/special-string-again.ts @@ -0,0 +1,55 @@ +/** + * + * A string is said to be a special string if either of two conditions is met: + * All of the characters are the same, e.g. aaa. + * All characters except the middle one are the same, e.g. aadaa. + * + * A special substring is any substring of a string which meets one of those criteria. + * Given a string, determine how many special substrings can be formed from it. + * + * Example: + * + * s = mnonopoo // => contains 12 special substrings + * + * {m, n, o, n, o, p, o, o, non, ono, opo, oo} + * + */ +export function substrCount(n: number, s: string): number { + let total = 0 + + const groups: Array<{ char: string; length: number }> = [] + + // Group the same characters + let index = 0 + + while (index < n) { + const currentChar = s[index] + let length = 1 + + while (index + 1 < n && s[index + 1] === currentChar) { + length++ + index++ + } + + groups.push({ char: currentChar, length }) + index++ + } + + // Count substrings from identical character groups + for (const group of groups) { + total += (group.length * (group.length + 1)) / 2 + } + + // Count symmetric patterns (E.g aba, aabaa) + for (let k = 1; k < groups.length - 1; k++) { + const left = groups[k - 1] + const center = groups[k] + const right = groups[k + 1] + + if (center.length === 1 && left.char === right.char) { + total += Math.min(left.length, right.length) + } + } + + return total +}