acl_cpp.string
from acl_cpp.string import suffix_array, lcp_array, z_algorithm
string.suffix_array
# (1) vector<int> suffix_array(string s)
def suffix_array(s: str) -> list[int]
# (2) vector<int> suffix_array<ll>(vector<ll> s)
def suffix_array(s: list[int]) -> list[int]
# (3) vector<int> suffix_array(vector<int> s, int upper)
def suffix_array(s: list[int], upper: int) -> list[int]
Let \(n = \text{len}(s)\), returns an array sa
of length \(n\) as defined below.
sa
is a permutation of \((0, 1, \ldots, n-1)\).s[sa[i]:] < s[sa[i+1]:]
holds.
Constraints
(2) \(-2^{63} \leq s[i] \lt 2^{63}\)
(3) \(0 \leq s[i] \leq \text{upper} \lt 2^{31}\)
Complexity
(1) \(O(n)\)
(2) \(O(n \log n)\) time, \(O(n)\) space
(3) \(O(n + \mathrm{upper})\)
string.lcp_array
# (1) vector<int> lcp_array(string s, vector<int> sa)
def lcp_array(s: str, sa: list[int]) -> list[int]
# (2) vector<int> lcp_array<ll>(vector<ll> s, vector<int> sa)
def lcp_array(s: list[int], sa: list[int]) -> list[int]
Let \(n = \text{len}(s)\), returns an array lcp
of length \(n-1\) as defined below.
lcp[i]
is the length of the LCP (Longest Common Prefix) ofs[sa[i]:]
ands[sa[i+1]:]
.
Constraints
sa
is the Suffix Array ofs
.Behavior is undefined if this is not satisfied.
Complexity
\(O(n)\)
string.z_algorithm
# (1) vector<int> z_algorithm(string s)
def z_algorithm(s: str) -> list[int]
# (2) vector<int> z_algorithm<ll>(vector<ll> s)
def z_algorithm(s: list[int]) -> list[int]
Let \(n = \text{len}(s)\), returns an array z
of length \(n\) as defined below.
z[i]
is the length of the LCP (Longest Common Prefix) ofs
ands[i:]
.
Constraints
(2) \(-2^{63} \leq s[i] \lt 2^{63}\)
Complexity
\(O(n)\)
Examples
from acl_cpp.string import suffix_array
s = "missisippi"
sa = suffix_array(s)
answer = [
"i",
"ippi",
"isippi",
"issisippi",
"missisippi",
"pi",
"ppi",
"sippi",
"sisippi",
"ssisippi",
]
for i, t in zip(sa, answer):
assert s[i:] == t
AC code of https://atcoder.jp/contests/practice2/tasks/practice2_i
from acl_cpp.string import suffix_array, lcp_array
s = input()
n = len(s)
sa = suffix_array(s)
lcp = lcp_array(s, sa)
print(n * (n + 1) // 2 - sum(lcp))