diff --git a/src/main/java/com/thealgorithms/strings/LyndonFactorization.java b/src/main/java/com/thealgorithms/strings/LyndonFactorization.java
new file mode 100644
index 000000000000..3eb13b00d0fb
--- /dev/null
+++ b/src/main/java/com/thealgorithms/strings/LyndonFactorization.java
@@ -0,0 +1,61 @@
+package com.thealgorithms.strings;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Factorizes a string into its Lyndon words using Duval's algorithm.
+ *
+ *
Duval's algorithm runs in O(n) time and uses O(1) auxiliary working
+ * space, excluding the returned list and its strings.
+ *
+ *
Reference:
+ * https://cp-algorithms.com/string/lyndon_factorization.html
+ */
+public final class LyndonFactorization {
+ private LyndonFactorization() {
+ }
+
+ /**
+ * Returns the standard Lyndon factorization of {@code text}.
+ *
+ *
The returned factors are in non-increasing lexicographic order
+ * according to Java's UTF-16 code-unit ordering.
+ *
+ * @param text input string to factorize
+ * @return Lyndon factors in non-increasing lexicographic order
+ * @throws IllegalArgumentException if {@code text} is null
+ */
+ public static List factorize(String text) {
+ if (text == null) {
+ throw new IllegalArgumentException("text must not be null");
+ }
+
+ List factors = new ArrayList<>();
+ int n = text.length();
+ int start = 0;
+
+ while (start < n) {
+ int candidate = start + 1;
+ int match = start;
+
+ while (candidate < n && text.charAt(match) <= text.charAt(candidate)) {
+ if (text.charAt(match) < text.charAt(candidate)) {
+ match = start;
+ } else {
+ match++;
+ }
+ candidate++;
+ }
+
+ int length = candidate - match;
+
+ while (start <= match) {
+ factors.add(text.substring(start, start + length));
+ start += length;
+ }
+ }
+
+ return factors;
+ }
+}
diff --git a/src/test/java/com/thealgorithms/strings/LyndonFactorizationTest.java b/src/test/java/com/thealgorithms/strings/LyndonFactorizationTest.java
new file mode 100644
index 000000000000..4ecb86e2a99c
--- /dev/null
+++ b/src/test/java/com/thealgorithms/strings/LyndonFactorizationTest.java
@@ -0,0 +1,35 @@
+package com.thealgorithms.strings;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+class LyndonFactorizationTest {
+
+ @Test
+ void factorizesBanana() {
+ assertEquals(List.of("b", "an", "an", "a"), LyndonFactorization.factorize("banana"));
+ }
+
+ @Test
+ void factorizesRepeatedPattern() {
+ assertEquals(List.of("ab", "ab", "ab"), LyndonFactorization.factorize("ababab"));
+ }
+
+ @Test
+ void factorizesSingleCharacter() {
+ assertEquals(List.of("a"), LyndonFactorization.factorize("a"));
+ }
+
+ @Test
+ void factorizesEmptyString() {
+ assertEquals(List.of(), LyndonFactorization.factorize(""));
+ }
+
+ @Test
+ void rejectsNullInput() {
+ assertThrows(IllegalArgumentException.class, () -> LyndonFactorization.factorize(null));
+ }
+}