From 9b9bfd7f52fef56120e3a53bfc3b0501c83805ad Mon Sep 17 00:00:00 2001 From: Rosander0 Date: Wed, 10 Jun 2026 18:30:04 +0530 Subject: [PATCH 1/2] feat: add LongestCommonSubstring implementation --- pom.xml | 2 +- .../strings/LongestCommonSubstring.java | 55 +++++++++++++++++++ .../strings/LongestCommonSubstringTest.java | 36 ++++++++++++ 3 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/thealgorithms/strings/LongestCommonSubstring.java create mode 100644 src/test/java/com/thealgorithms/strings/LongestCommonSubstringTest.java diff --git a/pom.xml b/pom.xml index 6edd36f446d8..e54b83399e9f 100644 --- a/pom.xml +++ b/pom.xml @@ -119,7 +119,7 @@ com.github.spotbugs spotbugs-maven-plugin - 4.9.8.3 + 4.10.2.0 spotbugs-exclude.xml true diff --git a/src/main/java/com/thealgorithms/strings/LongestCommonSubstring.java b/src/main/java/com/thealgorithms/strings/LongestCommonSubstring.java new file mode 100644 index 000000000000..b2190316aff2 --- /dev/null +++ b/src/main/java/com/thealgorithms/strings/LongestCommonSubstring.java @@ -0,0 +1,55 @@ +package com.thealgorithms.strings; + +/** + * Longest Common Substring finds the longest string that is a + * contiguous substring of two input strings. + * Example: "abcdef" and "zcdemf" -> "cde" + * + * @see + * Wikipedia: Longest Common Substring + * + * author: Vraj Prajapati @Rosander0 + */ +public final class LongestCommonSubstring { + + private LongestCommonSubstring() { + // Utility class + } + + /** + * Finds the longest common substring of two strings. + * + * @param a First input string + * @param b Second input string + * @return The longest common substring, or empty string if none exists. + * If multiple substrings share the maximum length, the first one found is returned. + */ + public static String longestCommonSubstring(final String a, final String b) { + if (a == null || b == null || a.isEmpty() || b.isEmpty()) { + return ""; + } + + int[][] dp = new int[a.length() + 1][b.length() + 1]; + int maxLength = 0; + int endIndex = 0; + + for (int i = 1; i <= a.length(); i++) { + for (int j = 1; j <= b.length(); j++) { + if (a.charAt(i - 1) == b.charAt(j - 1)) { + dp[i][j] = dp[i - 1][j - 1] + 1; + if (dp[i][j] > maxLength) { + maxLength = dp[i][j]; + endIndex = i; + } + } else { + dp[i][j] = 0; + } + } + } + + if (maxLength == 0) { + return ""; + } + return a.substring(endIndex - maxLength, endIndex); + } +} diff --git a/src/test/java/com/thealgorithms/strings/LongestCommonSubstringTest.java b/src/test/java/com/thealgorithms/strings/LongestCommonSubstringTest.java new file mode 100644 index 000000000000..e54abcf2f1f3 --- /dev/null +++ b/src/test/java/com/thealgorithms/strings/LongestCommonSubstringTest.java @@ -0,0 +1,36 @@ +package com.thealgorithms.strings; +// author: Vraj Prajapati @Rosander0 + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +public class LongestCommonSubstringTest { + + @Test + public void testNullOrEmptyInputs() { + assertEquals("", LongestCommonSubstring.longestCommonSubstring(null, "abc")); + assertEquals("", LongestCommonSubstring.longestCommonSubstring("abc", null)); + assertEquals("", LongestCommonSubstring.longestCommonSubstring("", "abc")); + assertEquals("", LongestCommonSubstring.longestCommonSubstring("abc", "")); + } + + @Test + public void testNormalSubstrings() { + assertEquals("cde", LongestCommonSubstring.longestCommonSubstring("abcdef", "zcdemf")); + assertEquals("abc", LongestCommonSubstring.longestCommonSubstring("abc", "abc")); + assertEquals("cdef", LongestCommonSubstring.longestCommonSubstring("abcdef", "cdefgh")); + } + + @Test + public void testSingleCharacterAndNoMatch() { + assertEquals("a", LongestCommonSubstring.longestCommonSubstring("a", "a")); + assertEquals("", LongestCommonSubstring.longestCommonSubstring("abc", "xyz")); + } + + @Test + public void testMultipleMatchesFirstLongest() { + // Keeps the first matched longest substring when lengths are tied + assertEquals("abc", LongestCommonSubstring.longestCommonSubstring("abcXdef", "abcYdef")); + } +} From 702d07210bc6004e54b2e3a11b4ad9b354fe62a8 Mon Sep 17 00:00:00 2001 From: Rosander0 Date: Sat, 13 Jun 2026 14:05:52 +0530 Subject: [PATCH 2/2] feat: add TitleCase Implementation --- .../com/thealgorithms/strings/TitleCase.java | 43 +++++++++++++++++++ .../thealgorithms/strings/TitleCaseTest.java | 34 +++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 src/main/java/com/thealgorithms/strings/TitleCase.java create mode 100644 src/test/java/com/thealgorithms/strings/TitleCaseTest.java diff --git a/src/main/java/com/thealgorithms/strings/TitleCase.java b/src/main/java/com/thealgorithms/strings/TitleCase.java new file mode 100644 index 000000000000..c35ff8e3112f --- /dev/null +++ b/src/main/java/com/thealgorithms/strings/TitleCase.java @@ -0,0 +1,43 @@ +package com.thealgorithms.strings; + +/** + * Title Case converts a string so that the first letter of each word + * is capitalized and the rest are lowercase. + * Example: "the quick brown fox" -> "The Quick Brown Fox" + * + * @see + * Wikipedia: Title Case + */ +public final class TitleCase { + + private TitleCase() { + // Utility class + } + + /** + * Converts a string to title case. + * + * @param input The string to convert + * @return The title-cased string, or empty string if input is null/empty. + * If input contains only whitespace, it is returned as is. + */ + public static String toTitleCase(final String input) { + if (input == null || input.isEmpty()) { + return ""; + } + StringBuilder result = new StringBuilder(); + boolean capitalizeNext = true; + for (char c : input.toCharArray()) { + if (Character.isWhitespace(c)) { + capitalizeNext = true; + result.append(c); + } else if (capitalizeNext) { + result.append(Character.toUpperCase(c)); + capitalizeNext = false; + } else { + result.append(Character.toLowerCase(c)); + } + } + return result.toString(); + } +} diff --git a/src/test/java/com/thealgorithms/strings/TitleCaseTest.java b/src/test/java/com/thealgorithms/strings/TitleCaseTest.java new file mode 100644 index 000000000000..2821b520be7a --- /dev/null +++ b/src/test/java/com/thealgorithms/strings/TitleCaseTest.java @@ -0,0 +1,34 @@ +package com.thealgorithms.strings; +// author: Vraj Prajapati @Rosander0 + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +public class TitleCaseTest { + + @Test + public void testNullOrEmptyInputs() { + assertEquals("", TitleCase.toTitleCase(null)); + assertEquals("", TitleCase.toTitleCase("")); + } + + @Test + public void testSingleWord() { + assertEquals("Hello", TitleCase.toTitleCase("hello")); + assertEquals("Hello", TitleCase.toTitleCase("HELLO")); + assertEquals("A", TitleCase.toTitleCase("a")); + } + + @Test + public void testMultipleWords() { + assertEquals("The Quick Brown Fox", TitleCase.toTitleCase("the quick brown fox")); + assertEquals("The Quick Brown Fox", TitleCase.toTitleCase("THE QUICK BROWN FOX")); + assertEquals("Already Title Case", TitleCase.toTitleCase("already Title Case")); + } + + @Test + public void testWhitespace() { + assertEquals(" Spaces ", TitleCase.toTitleCase(" spaces ")); + } +}