Skip to content

Commit bcc5800

Browse files
committed
v0.1.3: Made string matching generic, fixed writer_to_file()
1 parent 97f73de commit bcc5800

File tree

5 files changed

+42
-25
lines changed

5 files changed

+42
-25
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "contest-algorithms"
3-
version = "0.1.2"
3+
version = "0.1.3"
44
authors = ["Aram Ebtekar"]
55
edition = "2018"
66

src/arq_tree.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ mod test {
289289
assert_eq!(pos, 2);
290290
assert_eq!(pos_zeros, -1);
291291
}
292-
292+
293293
#[test]
294294
fn test_range_sum() {
295295
let mut arq = ArqTree::<AssignSum>::new(vec![(0, 1); 10]);
@@ -301,11 +301,11 @@ mod test {
301301

302302
assert_eq!(arq.query(0, 9), (23, 10));
303303
}
304-
304+
305305
#[test]
306306
fn test_supply_demand() {
307307
let mut arq = ArqTree::<SupplyDemand>::new(vec![(0, 0, 0); 10]);
308-
308+
309309
arq.modify(1, 1, &(25, 100));
310310
arq.modify(3, 3, &(100, 30));
311311
arq.modify(9, 9, &(0, 20));

src/math/num.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub fn fast_gcd(mut a: i64, mut b: i64) -> i64 {
1414
}
1515

1616
/// Represents a fraction reduced to lowest terms
17-
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
17+
#[derive(Clone, Copy, Eq, PartialEq, Debug, Hash)]
1818
pub struct Rational {
1919
pub num: i64,
2020
pub den: i64,
@@ -170,7 +170,7 @@ impl Div for Complex {
170170
/// [1, 2^31.5] will work. If MOD is not prime, ring operations are still valid
171171
/// but recip() and division are not. Note that the latter operations are also
172172
/// the slowest, so precompute any inverses that you intend to use frequently.
173-
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
173+
#[derive(Clone, Copy, Eq, PartialEq, Debug, Hash)]
174174
pub struct Field {
175175
pub val: i64,
176176
}

src/scanner.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ pub fn scanner_from_file(filename: &str) -> Scanner<io::BufReader<std::fs::File>
7676
}
7777

7878
pub fn writer_to_file(filename: &str) -> io::BufWriter<std::fs::File> {
79-
let file = std::fs::File::open(filename).expect("Output file not found");
79+
let file = std::fs::File::create(filename).expect("Output file not found");
8080
io::BufWriter::new(file)
8181
}
8282

src/string_proc.rs

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,46 @@
11
//! String processing algorithms.
22
33
/// Data structure for Knuth-Morris-Pratt string matching against a pattern.
4-
pub struct Matcher<'a> {
4+
pub struct Matcher<'a, T> {
55
/// The string pattern to search for.
6-
pub pattern: &'a [u8],
6+
pub pattern: &'a [T],
77
/// KMP match failure automaton. fail[i] is the length of the longest
88
/// proper prefix-suffix of pattern[0...i].
99
pub fail: Vec<usize>,
1010
}
1111

12-
impl<'a> Matcher<'a> {
12+
impl<'a, T: Eq> Matcher<'a, T> {
1313
/// Precomputes the automaton that allows linear-time string matching.
1414
///
15+
/// # Example
16+
///
17+
/// ```
18+
/// use contest_algorithms::string_proc::Matcher;
19+
/// let utf8_string = "hello";
20+
///
21+
/// let match_from_byte_literal = Matcher::new(b"hello");
22+
///
23+
/// let match_from_bytes = Matcher::new(utf8_string.as_bytes());
24+
///
25+
/// let vec_char: Vec<char> = utf8_string.chars().collect();
26+
/// let match_from_chars = Matcher::new(&vec_char);
27+
///
28+
/// let vec_int = vec![4, -3, 1];
29+
/// let match_from_ints = Matcher::new(&vec_int);
30+
/// ```
31+
///
1532
/// # Panics
1633
///
1734
/// Panics if pattern is empty.
18-
pub fn new(pattern: &'a [u8]) -> Self {
35+
pub fn new(pattern: &'a [T]) -> Self {
1936
let mut fail = Vec::with_capacity(pattern.len());
2037
fail.push(0);
2138
let mut len = 0;
22-
for &ch in &pattern[1..] {
23-
while len > 0 && pattern[len] != ch {
39+
for ch in &pattern[1..] {
40+
while len > 0 && pattern[len] != *ch {
2441
len = fail[len - 1];
2542
}
26-
if pattern[len] == ch {
43+
if pattern[len] == *ch {
2744
len += 1;
2845
}
2946
fail.push(len);
@@ -33,17 +50,17 @@ impl<'a> Matcher<'a> {
3350

3451
/// KMP algorithm, sets matches[i] = length of longest prefix of pattern
3552
/// matching a suffix of text[0...i].
36-
pub fn kmp_match(&self, text: &[u8]) -> Vec<usize> {
53+
pub fn kmp_match(&self, text: &[T]) -> Vec<usize> {
3754
let mut matches = Vec::with_capacity(text.len());
3855
let mut len = 0;
39-
for &ch in text {
56+
for ch in text {
4057
if len == self.pattern.len() {
4158
len = self.fail[len - 1];
4259
}
43-
while len > 0 && self.pattern[len] != ch {
60+
while len > 0 && self.pattern[len] != *ch {
4461
len = self.fail[len - 1];
4562
}
46-
if self.pattern[len] == ch {
63+
if self.pattern[len] == *ch {
4764
len += 1;
4865
}
4966
matches.push(len);
@@ -151,7 +168,7 @@ impl<K: std::hash::Hash + Eq + Default> Trie<K> {
151168
node.count += 1;
152169

153170
for ch in word {
154-
node = { node }.branches.entry(ch).or_insert_with(Default::default);
171+
node = { node }.branches.entry(ch).or_default();
155172
node.count += 1;
156173
}
157174
}
@@ -177,7 +194,7 @@ impl<K: std::hash::Hash + Eq + Default> Trie<K> {
177194
/// # Panics
178195
///
179196
/// Panics if text is empty.
180-
pub fn palindromes(text: &[u8]) -> Vec<usize> {
197+
pub fn palindromes<T: Eq>(text: &[T]) -> Vec<usize> {
181198
let mut pal = Vec::with_capacity(2 * text.len() - 1); // only mutable var!
182199
pal.push(1);
183200
while pal.len() < pal.capacity() {
@@ -210,8 +227,8 @@ mod test {
210227

211228
#[test]
212229
fn test_kmp() {
213-
let text = "banana".as_bytes();
214-
let pattern = "ana".as_bytes();
230+
let text = b"banana";
231+
let pattern = b"ana";
215232

216233
let matches = Matcher::new(pattern).kmp_match(text);
217234

@@ -220,8 +237,8 @@ mod test {
220237

221238
#[test]
222239
fn test_suffix_array() {
223-
let text1 = "bobocel".as_bytes();
224-
let text2 = "banana".as_bytes();
240+
let text1 = b"bobocel";
241+
let text2 = b"banana";
225242

226243
let sfx1 = SuffixArray::new(text1);
227244
let sfx2 = SuffixArray::new(text2);
@@ -261,7 +278,7 @@ mod test {
261278

262279
#[test]
263280
fn test_palindrome() {
264-
let text = "banana".as_bytes();
281+
let text = b"banana";
265282

266283
let pal_len = palindromes(text);
267284

0 commit comments

Comments
 (0)