pub fn lpf(lpf_out: &mut [u32], mut sa: Vec<u32>, mut lcp_in: Vec<u32>, n: usize) {
debug_assert!(lpf_out.len() >= n);
if n == 0 {
return;
}
if n == 1 {
lpf_out[0] = 0;
return;
}
sa.push(0);
lcp_in.push(0);
let mut stack: Vec<(u32, u32)> = Vec::new();
stack.push((0, sa[0] + 1));
for i in 1..=n {
let mut lcp = lcp_in[i];
while let Some(&(top_len, top_pos)) = stack.last() {
if sa[i] + 1 >= top_pos {
break;
}
let target = (top_pos - 1) as usize;
if target < lpf_out.len() {
lpf_out[target] = top_len.max(lcp);
}
lcp = top_len.min(lcp);
stack.pop();
}
if i < n {
stack.push((lcp, sa[i] + 1));
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::suffix_array::{build_lcp, build_suffix_array};
#[test]
fn lpf_banana() {
let text = b"banana";
let sa = build_suffix_array(text);
let lcp = build_lcp(text, &sa);
let mut out = vec![0u32; text.len()];
lpf(&mut out, sa, lcp, text.len());
assert_eq!(out.len(), 6);
}
}