Content-Length: 5982 | pFad | http://github.com/TheAlgorithms/JavaScript/pull/1758.patch
thub.com
From d33b0abbf373933525668ef49f74debc010aca00 Mon Sep 17 00:00:00 2001
From: rudrajiii
Date: Mon, 28 Oct 2024 01:43:39 +0530
Subject: [PATCH] feat: implement Booth's algorithm for lexicographically
minimal rotation of a string.
---
String/BoothsAlgorithm.js | 80 +++++++++++++++++++++++++++++
String/test/BoothsAlgorithm.test.js | 53 +++++++++++++++++++
2 files changed, 133 insertions(+)
create mode 100644 String/BoothsAlgorithm.js
create mode 100644 String/test/BoothsAlgorithm.test.js
diff --git a/String/BoothsAlgorithm.js b/String/BoothsAlgorithm.js
new file mode 100644
index 0000000000..b2335146e7
--- /dev/null
+++ b/String/BoothsAlgorithm.js
@@ -0,0 +1,80 @@
+/**
+ * Booth's Algorithm finds the lexicographically minimal rotation of a string.
+ * Time Complexity: O(n) - Linear time where n is the length of input string
+ * Space Complexity: O(n) - Linear space for failure function array
+ * For More Visit - https://en.wikipedia.org/wiki/Booth%27s_multiplication_algorithm
+ * @example
+ * Input: "baca"
+ * All possible rotations:
+ * - "baca"
+ * - "acab"
+ * - "caba"
+ * - "abac"
+ * Output: "abac" (lexicographically smallest)
+ *
+ * How it works:
+ * 1. Doubles the input string to handle all rotations
+ * 2. Uses failure function (similar to KMP) to find minimal rotation
+ * 3. Maintains a pointer to the start of minimal rotation found so far
+
+ * @param {string} str - Input string to find minimal rotation
+ * @returns {string} - Lexicographically minimal rotation of the input string
+ * @throws {Error} - If input is not a string or is empty
+ */
+export function findMinimalRotation(str) {
+ if (typeof str !== 'string') {
+ throw new Error('Input must be a string')
+ }
+
+ if (str.length === 0) {
+ throw new Error('Input string cannot be empty')
+ }
+
+ // Double the string for rotation comparison
+ // This allows us to check all rotations by just sliding a window
+ const s = str + str
+ const n = s.length
+
+ // Initialize failure function array
+ const f = new Array(n).fill(-1)
+ let k = 0 // Starting position of minimal rotation
+
+ //Algorithm's implementation
+ // Iterate through the doubled string
+ // j is the current position we're examining
+ for (let j = 1; j < n; j++) {
+ // i is the length of the matched prefix in the current candidate
+ // Get the failure function value for the previous position
+ let i = f[j - k - 1]
+ // This loop handles the case when we need to update our current minimal rotation
+ // It compares characters and finds if there's a better (lexicographically smaller) rotation
+ while (i !== -1 && s[j] !== s[k + i + 1]) {
+ // If we find a smaller character, we've found a better rotation
+ // Update k to the new starting position
+ if (s[j] < s[k + i + 1]) {
+ // j-i-1 gives us the starting position of the new minimal rotation
+ k = j - i - 1
+ }
+ // Update i using the failure function to try shorter prefixes
+ i = f[i]
+ }
+
+ // This block updates the failure function and handles new character comparisons
+ if (i === -1 && s[j] !== s[k + i + 1]) {
+ // If current character is smaller, update the minimal rotation start
+ if (s[j] < s[k + i + 1]) {
+ k = j
+ }
+ //If no match found,mark failure function accordingly
+ f[j - k] = -1
+ } else {
+ //If match found, extend the matched length
+ f[j - k] = i + 1
+ }
+ }
+ // After finding k (the starting position of minimal rotation):
+ // 1. slice(k): Take substring from position k to end
+ // 2. slice(0, k): Take substring from start to position k
+ // 3. Concatenate them to get the minimal rotation
+ return str.slice(k) + str.slice(0, k)
+}
diff --git a/String/test/BoothsAlgorithm.test.js b/String/test/BoothsAlgorithm.test.js
new file mode 100644
index 0000000000..f219820199
--- /dev/null
+++ b/String/test/BoothsAlgorithm.test.js
@@ -0,0 +1,53 @@
+import { findMinimalRotation } from '../BoothsAlgorithm'
+
+describe('BoothsAlgorithm', () => {
+ it('should throw an error if input is not a string', () => {
+ expect(() => findMinimalRotation(null)).toThrow('Input must be a string')
+ expect(() => findMinimalRotation(undefined)).toThrow(
+ 'Input must be a string'
+ )
+ expect(() => findMinimalRotation(123)).toThrow('Input must be a string')
+ expect(() => findMinimalRotation([])).toThrow('Input must be a string')
+ })
+
+ it('should throw an error if input string is empty', () => {
+ expect(() => findMinimalRotation('')).toThrow(
+ 'Input string cannot be empty'
+ )
+ })
+
+ it('should find minimal rotation for simple strings', () => {
+ expect(findMinimalRotation('abc')).toBe('abc')
+ expect(findMinimalRotation('bca')).toBe('abc')
+ expect(findMinimalRotation('cab')).toBe('abc')
+ })
+
+ it('should handle strings with repeated characters', () => {
+ expect(findMinimalRotation('aaaa')).toBe('aaaa')
+ expect(findMinimalRotation('aaab')).toBe('aaab')
+ expect(findMinimalRotation('baaa')).toBe('aaab')
+ })
+
+ it('should handle strings with special characters', () => {
+ expect(findMinimalRotation('12#$')).toBe('#$12')
+ expect(findMinimalRotation('@abc')).toBe('@abc')
+ expect(findMinimalRotation('xyz!')).toBe('!xyz')
+ })
+
+ it('should handle longer strings', () => {
+ expect(findMinimalRotation('algorithm')).toBe('algorithm')
+ expect(findMinimalRotation('rithmalgo')).toBe('algorithm')
+ expect(findMinimalRotation('gorithmal')).toBe('algorithm')
+ })
+
+ it('should be case sensitive', () => {
+ expect(findMinimalRotation('AbC')).toBe('AbC')
+ expect(findMinimalRotation('BcA')).toBe('ABc')
+ expect(findMinimalRotation('CAb')).toBe('AbC')
+ })
+
+ it('should handle palindromes', () => {
+ expect(findMinimalRotation('radar')).toBe('adarr')
+ expect(findMinimalRotation('level')).toBe('ellev')
+ })
+})
--- a PPN by Garber Painting Akron. With Image Size Reduction included!Fetched URL: http://github.com/TheAlgorithms/JavaScript/pull/1758.patch
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy