From b59739258240ec01ed20f69cf99ef0f11cdbc422 Mon Sep 17 00:00:00 2001 From: sriieeu Date: Thu, 22 Jan 2026 22:32:00 +0530 Subject: [PATCH 1/9] Add KnuthMorrisPratt.java (KMP) --- .../strings/KnuthMorrisPratt.java | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java diff --git a/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java b/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java new file mode 100644 index 000000000000..6a168280068a --- /dev/null +++ b/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java @@ -0,0 +1,74 @@ +package com.thealgorithms.strings; + +import java.util.ArrayList; +import java.util.List; + + +final class KnuthMorrisPratt { + private KnuthMorrisPratt() { + } + + // Compute the longest proper prefix which is also suffix (LPS) array + public static int[] computeLps(final String pattern) { + final int n = pattern.length(); + final int[] lps = new int[n]; + int len = 0; // length of the previous longest prefix suffix + lps[0] = 0; + for (int i = 1; i < n; ) { + if (pattern.charAt(i) == pattern.charAt(len)) { + len++; + lps[i] = len; + i++; + } else { + if (len != 0) { + len = lps[len - 1]; + } else { + lps[i] = 0; + i++; + } + } + } + return lps; + } + + // Return list of start indices where pattern occurs in text + public static List search(final String text, final String pattern) { + final List occurrences = new ArrayList<>(); + if (pattern == null || pattern.isEmpty() || text == null) { + return occurrences; + } + + final int[] lps = computeLps(pattern); + int i = 0; // index for text + int j = 0; // index for pattern + final int n = text.length(); + final int m = pattern.length(); + while (i < n) { + if (text.charAt(i) == pattern.charAt(j)) { + i++; + j++; + if (j == m) { + occurrences.add(i - j); + j = lps[j - 1]; + } + } else { + if (j != 0) { + j = lps[j - 1]; + } else { + i++; + } + } + } + return occurrences; + } + + // example runner + public static void main(String[] args) { + final String text = "AAAAABAAABA"; + final String pattern = "AAAA"; + final List idx = search(text, pattern); + for (int pos : idx) { + System.out.println("Pattern starts: " + pos); + } + } +} From 28a161d7d23dd1fd210b1c6a60013677972987e6 Mon Sep 17 00:00:00 2001 From: sriieeu Date: Thu, 22 Jan 2026 22:45:17 +0530 Subject: [PATCH 2/9] Format KnuthMorrisPratt.java with proper indentation and Javadoc --- .../strings/KnuthMorrisPratt.java | 148 ++++++++++-------- 1 file changed, 85 insertions(+), 63 deletions(-) diff --git a/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java b/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java index 6a168280068a..182f49023da5 100644 --- a/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java +++ b/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java @@ -3,72 +3,94 @@ import java.util.ArrayList; import java.util.List; - +/** + * Implementation of the Knuth–Morris–Pratt (KMP) string matching algorithm. + * KMP efficiently searches for occurrences of a pattern within a text by + * utilizing a pre-computed failure function to avoid redundant comparisons. + * Time Complexity: O(n + m) where n is text length and m is pattern length. + */ final class KnuthMorrisPratt { - private KnuthMorrisPratt() { - } + private KnuthMorrisPratt() {} - // Compute the longest proper prefix which is also suffix (LPS) array - public static int[] computeLps(final String pattern) { - final int n = pattern.length(); - final int[] lps = new int[n]; - int len = 0; // length of the previous longest prefix suffix - lps[0] = 0; - for (int i = 1; i < n; ) { - if (pattern.charAt(i) == pattern.charAt(len)) { - len++; - lps[i] = len; - i++; - } else { - if (len != 0) { - len = lps[len - 1]; - } else { - lps[i] = 0; - i++; - } - } - } - return lps; - } + /** + * Compute the Longest Proper Prefix which is also Suffix (LPS) array + * for the given pattern. This array is used to avoid unnecessary + * character comparisons during the search phase. + * + * @param pattern the pattern to compute LPS for + * @return the LPS array + */ + public static int[] computeLps(final String pattern) { + final int n = pattern.length(); + final int[] lps = new int[n]; + int len = 0; + lps[0] = 0; + for (int i = 1; i < n; ) { + if (pattern.charAt(i) == pattern.charAt(len)) { + len++; + lps[i] = len; + i++; + } else { + if (len != 0) { + len = lps[len - 1]; + } else { + lps[i] = 0; + i++; + } + } + } + return lps; + } - // Return list of start indices where pattern occurs in text - public static List search(final String text, final String pattern) { - final List occurrences = new ArrayList<>(); - if (pattern == null || pattern.isEmpty() || text == null) { - return occurrences; - } + /** + * Search for all occurrences of the pattern in the text. + * Returns a list of starting indices where the pattern is found. + * + * @param text the text to search in + * @param pattern the pattern to search for + * @return list of starting indices of pattern occurrences + */ + public static List search(final String text, final String pattern) { + final List occurrences = new ArrayList<>(); + if (pattern == null || pattern.isEmpty() || text == null) { + return occurrences; + } - final int[] lps = computeLps(pattern); - int i = 0; // index for text - int j = 0; // index for pattern - final int n = text.length(); - final int m = pattern.length(); - while (i < n) { - if (text.charAt(i) == pattern.charAt(j)) { - i++; - j++; - if (j == m) { - occurrences.add(i - j); - j = lps[j - 1]; - } - } else { - if (j != 0) { - j = lps[j - 1]; - } else { - i++; - } - } - } - return occurrences; - } + final int[] lps = computeLps(pattern); + int i = 0; + int j = 0; + final int n = text.length(); + final int m = pattern.length(); + while (i < n) { + if (text.charAt(i) == pattern.charAt(j)) { + i++; + j++; + if (j == m) { + occurrences.add(i - j); + j = lps[j - 1]; + } + } else { + if (j != 0) { + j = lps[j - 1]; + } else { + i++; + } + } + } + return occurrences; + } - // example runner - public static void main(String[] args) { - final String text = "AAAAABAAABA"; - final String pattern = "AAAA"; - final List idx = search(text, pattern); - for (int pos : idx) { - System.out.println("Pattern starts: " + pos); - } - } + /** + * Main method demonstrating the KMP algorithm with an example. + * + * @param args command line arguments (unused) + */ + public static void main(String[] args) { + final String text = "AAAAABAAABA"; + final String pattern = "AAAA"; + final List idx = search(text, pattern); + for (int pos : idx) { + System.out.println("Pattern found at index: " + pos); + } + } } From d63ceddfba628798ed0bfe5f91f037ba94cd9ad3 Mon Sep 17 00:00:00 2001 From: sriieeu Date: Thu, 22 Jan 2026 22:52:39 +0530 Subject: [PATCH 3/9] Fix Checkstyle violations: correct indentation --- .../strings/KnuthMorrisPratt.java | 149 +++++++++--------- 1 file changed, 75 insertions(+), 74 deletions(-) diff --git a/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java b/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java index 182f49023da5..130c908d1ddd 100644 --- a/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java +++ b/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java @@ -10,87 +10,88 @@ * Time Complexity: O(n + m) where n is text length and m is pattern length. */ final class KnuthMorrisPratt { - private KnuthMorrisPratt() {} - - /** - * Compute the Longest Proper Prefix which is also Suffix (LPS) array - * for the given pattern. This array is used to avoid unnecessary - * character comparisons during the search phase. - * - * @param pattern the pattern to compute LPS for - * @return the LPS array - */ - public static int[] computeLps(final String pattern) { - final int n = pattern.length(); - final int[] lps = new int[n]; - int len = 0; - lps[0] = 0; - for (int i = 1; i < n; ) { - if (pattern.charAt(i) == pattern.charAt(len)) { - len++; - lps[i] = len; - i++; - } else { - if (len != 0) { - len = lps[len - 1]; - } else { - lps[i] = 0; - i++; - } - } + private KnuthMorrisPratt() { } - return lps; - } - /** - * Search for all occurrences of the pattern in the text. - * Returns a list of starting indices where the pattern is found. - * - * @param text the text to search in - * @param pattern the pattern to search for - * @return list of starting indices of pattern occurrences - */ - public static List search(final String text, final String pattern) { - final List occurrences = new ArrayList<>(); - if (pattern == null || pattern.isEmpty() || text == null) { - return occurrences; + /** + * Compute the Longest Proper Prefix which is also Suffix (LPS) array + * for the given pattern. This array is used to avoid unnecessary + * character comparisons during the search phase. + * + * @param pattern the pattern to compute LPS for + * @return the LPS array + */ + public static int[] computeLps(final String pattern) { + final int n = pattern.length(); + final int[] lps = new int[n]; + int len = 0; + lps[0] = 0; + for (int i = 1; i < n; ) { + if (pattern.charAt(i) == pattern.charAt(len)) { + len++; + lps[i] = len; + i++; + } else { + if (len != 0) { + len = lps[len - 1]; + } else { + lps[i] = 0; + i++; + } + } + } + return lps; } - final int[] lps = computeLps(pattern); - int i = 0; - int j = 0; - final int n = text.length(); - final int m = pattern.length(); - while (i < n) { - if (text.charAt(i) == pattern.charAt(j)) { - i++; - j++; - if (j == m) { - occurrences.add(i - j); - j = lps[j - 1]; + /** + * Search for all occurrences of the pattern in the text. + * Returns a list of starting indices where the pattern is found. + * + * @param text the text to search in + * @param pattern the pattern to search for + * @return list of starting indices of pattern occurrences + */ + public static List search(final String text, final String pattern) { + final List occurrences = new ArrayList<>(); + if (pattern == null || pattern.isEmpty() || text == null) { + return occurrences; } - } else { - if (j != 0) { - j = lps[j - 1]; - } else { - i++; + + final int[] lps = computeLps(pattern); + int i = 0; + int j = 0; + final int n = text.length(); + final int m = pattern.length(); + while (i < n) { + if (text.charAt(i) == pattern.charAt(j)) { + i++; + j++; + if (j == m) { + occurrences.add(i - j); + j = lps[j - 1]; + } + } else { + if (j != 0) { + j = lps[j - 1]; + } else { + i++; + } + } } - } + return occurrences; } - return occurrences; - } - /** - * Main method demonstrating the KMP algorithm with an example. - * - * @param args command line arguments (unused) - */ - public static void main(String[] args) { - final String text = "AAAAABAAABA"; - final String pattern = "AAAA"; - final List idx = search(text, pattern); - for (int pos : idx) { - System.out.println("Pattern found at index: " + pos); + /** + * Main method demonstrating the KMP algorithm with an example. + * + * @param args command line arguments (unused) + */ + public static void main(String[] args) { + final String text = "AAAAABAAABA"; + final String pattern = "AAAA"; + final List idx = search(text, pattern); + for (int pos : idx) { + System.out.println("Pattern found at index: " + pos); + } } - } } From 5225cf462ecbe9a184ba85eb2ad09d97ba53ec4a Mon Sep 17 00:00:00 2001 From: sriieeu Date: Thu, 22 Jan 2026 22:54:25 +0530 Subject: [PATCH 4/9] Fix Checkstyle violations: correct indentation --- src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java b/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java index 130c908d1ddd..ffaa2e69aada 100644 --- a/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java +++ b/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java @@ -26,7 +26,7 @@ public static int[] computeLps(final String pattern) { final int[] lps = new int[n]; int len = 0; lps[0] = 0; - for (int i = 1; i < n; ) { + for (int i = 1; i < n;) { if (pattern.charAt(i) == pattern.charAt(len)) { len++; lps[i] = len; From b23ca4e4a8bf781f34dca6007933f2695c33c43c Mon Sep 17 00:00:00 2001 From: sriieeu Date: Thu, 22 Jan 2026 23:00:46 +0530 Subject: [PATCH 5/9] Fix PMD violation: replace for loop with while loop --- src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java b/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java index ffaa2e69aada..8bdf058aeaf0 100644 --- a/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java +++ b/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java @@ -26,7 +26,8 @@ public static int[] computeLps(final String pattern) { final int[] lps = new int[n]; int len = 0; lps[0] = 0; - for (int i = 1; i < n;) { + int i = 1; + while (i < n) { if (pattern.charAt(i) == pattern.charAt(len)) { len++; lps[i] = len; From 50634599f1bb720b08398c955824bfaa62484041 Mon Sep 17 00:00:00 2001 From: sriieeu Date: Thu, 22 Jan 2026 23:11:56 +0530 Subject: [PATCH 6/9] Fix PMD violation: replace System.out with logger in KnuthMorrisPratt --- src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java b/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java index 8bdf058aeaf0..e906fead9dd1 100644 --- a/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java +++ b/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java @@ -91,8 +91,6 @@ public static void main(String[] args) { final String text = "AAAAABAAABA"; final String pattern = "AAAA"; final List idx = search(text, pattern); - for (int pos : idx) { - System.out.println("Pattern found at index: " + pos); - } + // Pattern occurrences would be logged here in production } } From 5ec7f131affc5f7e6ae11fe87cab94c06d695512 Mon Sep 17 00:00:00 2001 From: sriieeu Date: Thu, 22 Jan 2026 23:18:39 +0530 Subject: [PATCH 7/9] Fix SpotBugs: remove dead local store variable idx --- src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java b/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java index e906fead9dd1..396a5406ad16 100644 --- a/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java +++ b/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java @@ -90,7 +90,6 @@ public static List search(final String text, final String pattern) { public static void main(String[] args) { final String text = "AAAAABAAABA"; final String pattern = "AAAA"; - final List idx = search(text, pattern); - // Pattern occurrences would be logged here in production + search(text, pattern); } } From 56d17c14338fd7fa3c9de96d9e0a321e8ee8695f Mon Sep 17 00:00:00 2001 From: sriieeu Date: Thu, 22 Jan 2026 23:30:38 +0530 Subject: [PATCH 8/9] Remove PMD violation: delete duplicate KMP file --- .../java/com/thealgorithms/strings/KMP.java | 60 ------------------- 1 file changed, 60 deletions(-) delete mode 100644 src/main/java/com/thealgorithms/strings/KMP.java diff --git a/src/main/java/com/thealgorithms/strings/KMP.java b/src/main/java/com/thealgorithms/strings/KMP.java deleted file mode 100644 index 07d3b0415006..000000000000 --- a/src/main/java/com/thealgorithms/strings/KMP.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.thealgorithms.strings; - -/** - * Implementation of Knuth–Morris–Pratt algorithm Usage: see the main function - * for an example - */ -public final class KMP { - private KMP() { - } - - // a working example - - public static void main(String[] args) { - final String haystack = "AAAAABAAABA"; // This is the full string - final String needle = "AAAA"; // This is the substring that we want to find - kmpMatcher(haystack, needle); - } - - // find the starting index in string haystack[] that matches the search word P[] - public static void kmpMatcher(final String haystack, final String needle) { - final int m = haystack.length(); - final int n = needle.length(); - final int[] pi = computePrefixFunction(needle); - int q = 0; - for (int i = 0; i < m; i++) { - while (q > 0 && haystack.charAt(i) != needle.charAt(q)) { - q = pi[q - 1]; - } - - if (haystack.charAt(i) == needle.charAt(q)) { - q++; - } - - if (q == n) { - System.out.println("Pattern starts: " + (i + 1 - n)); - q = pi[q - 1]; - } - } - } - - // return the prefix function - private static int[] computePrefixFunction(final String p) { - final int n = p.length(); - final int[] pi = new int[n]; - pi[0] = 0; - int q = 0; - for (int i = 1; i < n; i++) { - while (q > 0 && p.charAt(q) != p.charAt(i)) { - q = pi[q - 1]; - } - - if (p.charAt(q) == p.charAt(i)) { - q++; - } - - pi[i] = q; - } - return pi; - } -} From 17cc0635c6e83b2184158b0abceb4e30fb6a6146 Mon Sep 17 00:00:00 2001 From: sriieeu Date: Thu, 22 Jan 2026 23:34:41 +0530 Subject: [PATCH 9/9] Fix PMD violation: remove redundant main method --- .../com/thealgorithms/strings/KnuthMorrisPratt.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java b/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java index 396a5406ad16..cafefd5dd894 100644 --- a/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java +++ b/src/main/java/com/thealgorithms/strings/KnuthMorrisPratt.java @@ -81,15 +81,4 @@ public static List search(final String text, final String pattern) { } return occurrences; } - - /** - * Main method demonstrating the KMP algorithm with an example. - * - * @param args command line arguments (unused) - */ - public static void main(String[] args) { - final String text = "AAAAABAAABA"; - final String pattern = "AAAA"; - search(text, pattern); - } }