Skip to content

Commit 44c06fa

Browse files
committed
Add Lyndon factorization with Duval's algorithm
1 parent 7f81fcd commit 44c06fa

1 file changed

Lines changed: 49 additions & 0 deletions

File tree

‎strings/lyndon_factorization.py‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
"""Factor a string into Lyndon words using Duval's linear-time algorithm.
2+
3+
https://cp-algorithms.com/string/lyndon_factorization.html
4+
"""
5+
6+
7+
def lyndon_factorization(text: str) -> list[str]:
8+
"""Return the unique non-increasing sequence of Lyndon words in ``text``.
9+
10+
A Lyndon word is strictly smaller than each of its nontrivial rotations.
11+
The empty string has an empty factorization.
12+
13+
>>> lyndon_factorization("banana")
14+
['b', 'an', 'an', 'a']
15+
>>> lyndon_factorization("abab")
16+
['ab', 'ab']
17+
>>> lyndon_factorization("aaaa")
18+
['a', 'a', 'a', 'a']
19+
>>> lyndon_factorization("")
20+
[]
21+
>>> lyndon_factorization(123)
22+
Traceback (most recent call last):
23+
...
24+
TypeError: text must be a string
25+
"""
26+
if not isinstance(text, str):
27+
raise TypeError("text must be a string")
28+
29+
factors: list[str] = []
30+
start = 0
31+
length = len(text)
32+
33+
while start < length:
34+
candidate = start
35+
end = start + 1
36+
37+
while end < length and text[candidate] <= text[end]:
38+
if text[candidate] < text[end]:
39+
candidate = start
40+
else:
41+
candidate += 1
42+
end += 1
43+
44+
factor_length = end - candidate
45+
while start <= candidate:
46+
factors.append(text[start : start + factor_length])
47+
start += factor_length
48+
49+
return factors

0 commit comments

Comments
 (0)