Ответ 1
Исправление для этой проблемы было сегодня объединено. Это означает, что он должен быть частью следующего вечера, и ожидается, что он будет выпущен в Rust 1.3. Исправление возобновило реализацию Двусторонней подстроки, которую Rust использовал и адаптировал к новому API-интерфейсу в стандартной библиотеке.
Двунаправленный алгоритм является хорошим совпадением для Rust libcore, поскольку он представляет собой алгоритм поиска линейной временной подстроки, который использует O (1) пространство и не нуждается в динамическом распределении.
Конкретная реализация содержит простое дополнение, которое будет очень быстро отклонять этот конкретный запрос в вопросе (и нет, он не был написан из-за этого вопроса, он тоже был частью старого кода).
Во время настройки искатель вычисляет отпечаток пальца для иглы: для каждого байта в игле возьмите свои 6 разрядов, которые являются числом 0-63, затем установите соответствующий бит в переменной u64
byteset
.
let byteset = needle.iter().fold(0, |a, &b| (1 << ((b & 0x3f) as usize)) | a);
Так как игла содержит только "b", значение байта будет иметь только 34-й бит (98 & 63 == 34
).
Теперь мы можем проверить любой байт, может ли он быть частью иглы или нет. Если соответствующий бит не установлен в byteset
, игла не может совпадать. Каждый байт, который мы тестируем в стоге сена, в этом случае будет "a" (97 & 63 == 33
), и он не может совпадать. Таким образом, алгоритм будет читать один байт, отклонить его, а затем пропустить длину иглы.
fn byteset_contains(&self, byte: u8) -> bool {
(self.byteset >> ((byte & 0x3f) as usize)) & 1 != 0
}
// Quickly skip by large portions unrelated to our substring
if !self.byteset_contains(haystack[self.position + needle.len() - 1]) {
self.position += needle.len();
continue 'search;
}