@@ -49,8 +49,8 @@ impl<C: std::hash::Hash + Eq> Trie<C> {
49
49
pub struct Matcher < ' a , C : Eq > {
50
50
/// The string pattern to search for.
51
51
pub pattern : & ' a [ C ] ,
52
- /// KMP match failure automaton. fail[i] is the length of the longest
53
- /// proper prefix- suffix of pattern[0..=i].
52
+ /// KMP match failure automaton: fail[i] is the length of the longest
53
+ /// string that's both a proper prefix and a proper suffix of pattern[0..=i].
54
54
pub fail : Vec < usize > ,
55
55
}
56
56
@@ -316,18 +316,18 @@ pub fn palindromes(text: &[impl Eq]) -> Vec<usize> {
316
316
pal
317
317
}
318
318
319
- /// Z algorithm for computing an array Z[..], where Z[i] is the length of the
320
- /// longest text substring starting from index i that is **also a prefix** of
321
- /// the text.
319
+ /// Z algorithm: computes the array Z[..], where Z[i] is the length of the
320
+ /// longest text prefix of text[i..] that is **also a prefix** of text.
322
321
///
323
- /// This runs in O(n) time. It can be embedded in a larger algorithm, or used
324
- /// for string searching as an alternative to KMP above.
322
+ /// It runs in O(n) time, maintaining the invariant that l <= i and
323
+ /// text[0..r-l] == text[l..r]. It can be embedded in a larger algorithm,
324
+ /// or used for string searching as an alternative to KMP.
325
325
///
326
326
/// # Example
327
327
///
328
328
/// ```
329
329
/// use contest_algorithms::string_proc::z_algorithm;
330
- /// let z = z_algorithm("ababbababbabababbabababbababbaba".as_bytes() );
330
+ /// let z = z_algorithm(b "ababbababbabababbabababbababbaba");
331
331
/// assert_eq!(
332
332
/// z,
333
333
/// vec![
@@ -338,19 +338,18 @@ pub fn palindromes(text: &[impl Eq]) -> Vec<usize> {
338
338
/// ```
339
339
pub fn z_algorithm ( text : & [ impl Eq ] ) -> Vec < usize > {
340
340
let n = text. len ( ) ;
341
- let ( mut l, mut r) = ( 0 , 0 ) ;
342
- let mut z = vec ! [ 0 ; n ] ;
343
- z[ 0 ] = n ;
341
+ let ( mut l, mut r) = ( 1 , 1 ) ;
342
+ let mut z = Vec :: with_capacity ( n ) ;
343
+ z. push ( n ) ;
344
344
for i in 1 ..n {
345
- if i < r {
346
- z[ i] = min ( r - i, z[ i - l] ) ;
347
- }
348
- while i + z[ i] < n && text[ i + z[ i] ] == text[ z[ i] ] {
349
- z[ i] += 1 ;
350
- }
351
- if i + z[ i] > r {
345
+ if r > i + z[ i - l] {
346
+ z. push ( z[ i - l] ) ;
347
+ } else {
352
348
l = i;
353
- r = i + z[ i] ;
349
+ while r < i || ( r < n && text[ r - i] == text[ r] ) {
350
+ r += 1 ;
351
+ }
352
+ z. push ( r - i) ;
354
353
}
355
354
}
356
355
z
0 commit comments