Skip to content

Commit 71fa2f6

Browse files
Manacher (#39)
* add manacher * fix cargo doc
1 parent f10afed commit 71fa2f6

File tree

5 files changed

+75
-0
lines changed

5 files changed

+75
-0
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,7 @@ path = "examples/numbers/primes_factorize.rs"
7777
[[example]]
7878
name = "primes_is_prime"
7979
path = "examples/numbers/primes_is_prime.rs"
80+
81+
[[example]]
82+
name = "manacher"
83+
path = "examples/strings/manacher.rs"

examples/strings/manacher.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// verification-helper: PROBLEM https://judge.yosupo.jp/problem/enumerate_palindromes
2+
3+
use proconio::input;
4+
use programming_team_code_rust::strings::manacher::manacher;
5+
6+
fn main() {
7+
input! {
8+
s: String
9+
}
10+
11+
let man = manacher(&s.chars().collect::<Vec<_>>())
12+
.iter()
13+
.enumerate()
14+
.map(|(i, &x)| i - 2 * x + 1)
15+
.collect::<Vec<_>>();
16+
17+
println!(
18+
"{}",
19+
man.iter()
20+
.map(|&x| x.to_string())
21+
.collect::<Vec<_>>()
22+
.join(" ")
23+
);
24+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
pub mod data_structures;
33
pub mod graphs;
44
pub mod numbers;
5+
pub mod strings;

src/strings/manacher.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//! # Manacher's algorithm
2+
3+
/// See <https://codeforces.com/blog/entry/12143#comment-324162>
4+
///
5+
/// subarray [le, ri] has "center" i = le + ri
6+
///
7+
/// center 0 2 4 6 8
8+
/// string b a a b a
9+
/// center 1 3 5 7
10+
///
11+
/// man = {0, 1, 1, 0, 2, 3, 2, 4, 4}
12+
///
13+
/// # Example
14+
/// ```
15+
/// use programming_team_code_rust::strings::manacher::manacher;
16+
///
17+
/// assert_eq!(manacher(&"baaba".chars().collect::<Vec<_>>()), vec![0, 1, 1, 0, 2, 3, 2, 4, 4]);
18+
/// ```
19+
///
20+
/// # Complexity (n = s.len())
21+
/// - Time: O(n)
22+
/// - Space: O(n)
23+
pub fn manacher<T: std::cmp::PartialEq>(s: &[T]) -> Vec<usize> {
24+
if s.is_empty() {
25+
return vec![];
26+
}
27+
let n = s.len();
28+
let mut p = 0;
29+
let mut man = vec![0; 2 * n - 1];
30+
for i in 0..2 * n - 1 {
31+
let mut ri = if i <= 2 * (p - man[p]) {
32+
p - man[p].max(man[2 * p - i])
33+
} else {
34+
i / 2
35+
};
36+
man[i] = i - ri;
37+
while man[i] > 0 && ri + 1 < n && s[man[i] - 1] == s[ri + 1] {
38+
man[i] -= 1;
39+
ri += 1;
40+
p = i;
41+
}
42+
}
43+
man
44+
}

src/strings/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
//! # String Algorithms
2+
pub mod manacher;

0 commit comments

Comments
 (0)