competitive/string/
suffix_automaton.rs1use std::collections::HashMap;
2
3#[derive(Debug)]
4struct State {
5 next: HashMap<usize, usize>,
6 link: usize,
7 len: usize,
8}
9
10#[derive(Debug)]
11pub struct SuffixAutomaton {
12 states: Vec<State>,
13 last: usize,
14}
15
16impl Default for SuffixAutomaton {
17 fn default() -> Self {
18 Self {
19 states: vec![State {
20 next: HashMap::new(),
21 link: !0,
22 len: 0,
23 }],
24 last: 0,
25 }
26 }
27}
28
29impl SuffixAutomaton {
30 pub fn new() -> Self {
31 Self::default()
32 }
33
34 pub fn state_size(&self) -> usize {
35 self.states.len()
36 }
37
38 pub fn transitions(&self, state: usize) -> &HashMap<usize, usize> {
39 &self.states[state].next
40 }
41
42 pub fn length(&self, state: usize) -> usize {
43 self.states[state].len
44 }
45
46 pub fn link(&self, state: usize) -> usize {
47 self.states[state].link
48 }
49
50 pub fn number_of_substrings(&self) -> usize {
51 let mut total = 0;
52 for state in 1..self.state_size() {
53 let link = self.link(state);
54 total += self.length(state) - self.length(link);
55 }
56 total
57 }
58
59 fn push(&mut self, c: usize) {
60 let new_node = self.states.len();
61 let last = self.last;
62 self.states.push(State {
63 next: HashMap::new(),
64 link: !0,
65 len: self.states[last].len + 1,
66 });
67 let mut p = last;
68 while p != !0 && !self.states[p].next.contains_key(&c) {
69 self.states[p].next.insert(c, new_node);
70 p = self.states[p].link;
71 }
72 let q = if p == !0 { 0 } else { self.states[p].next[&c] };
73 if p == !0 || self.states[p].len + 1 == self.states[q].len {
74 self.states[new_node].link = q;
75 } else {
76 let new_q = self.states.len();
77 self.states.push(State {
78 next: self.states[q].next.clone(),
79 link: self.states[q].link,
80 len: self.states[p].len + 1,
81 });
82 self.states[q].link = new_q;
83 self.states[new_node].link = new_q;
84 while p != !0 && self.states[p].next[&c] == q {
85 self.states[p].next.insert(c, new_q);
86 p = self.states[p].link;
87 }
88 }
89 self.last = new_node;
90 }
91}
92
93impl FromIterator<usize> for SuffixAutomaton {
94 fn from_iter<I: IntoIterator<Item = usize>>(iter: I) -> Self {
95 let mut sa = SuffixAutomaton::new();
96 sa.extend(iter);
97 sa
98 }
99}
100
101impl Extend<usize> for SuffixAutomaton {
102 fn extend<T: IntoIterator<Item = usize>>(&mut self, iter: T) {
103 for c in iter {
104 self.push(c);
105 }
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112 use crate::tools::Xorshift;
113
114 #[test]
115 fn test_suffix_automaton() {
116 let mut rng = Xorshift::default();
117 for _ in 0..100 {
118 let csize = rng.random(1usize..=10);
119 let n = rng.random(1usize..=100);
120 let s: Vec<usize> = rng.random_iter(0usize..csize).take(n).collect();
121 let sa = SuffixAutomaton::from_iter(s.iter().cloned());
122 let mut len = vec![0; sa.state_size()];
123
124 for i in 0..n {
125 let mut state = 0;
126 for (j, &c) in s[i..].iter().enumerate() {
127 assert!(sa.transitions(state).contains_key(&c));
128 state = sa.transitions(state)[&c];
129 len[state] = len[state].max(j + 1);
130 }
131 }
132 for (state, &len) in len.iter().enumerate() {
133 assert_eq!(sa.length(state), len);
134 }
135 for state in 1..sa.state_size() {
136 assert_ne!(sa.link(state), !0);
137 }
138 }
139 }
140
141 #[test]
142 fn test_number_of_substrings() {
143 let mut rng = Xorshift::default();
144 for _ in 0..100 {
145 let csize = rng.random(1usize..=10);
146 let n = rng.random(1usize..=100);
147 let s: Vec<usize> = rng.random_iter(0usize..csize).take(n).collect();
148 let sa = SuffixAutomaton::from_iter(s.iter().cloned());
149 let mut substrings = std::collections::HashSet::new();
150 for i in 0..n {
151 for j in i + 1..=n {
152 substrings.insert(&s[i..j]);
153 }
154 }
155 assert_eq!(sa.number_of_substrings(), substrings.len());
156 }
157 }
158}