1032.字符流
链接:1032.字符流
难度:Hard
标签:设计、字典树、数组、字符串、数据流
简介:设计一个算法:接收一个字符流,并检查这些字符的后缀是否是字符串数组 words 中的一个字符串。
题解 1 - cpp
- 编辑时间:2023-03-24
- 执行用时:140ms
- 内存消耗:90.7MB
- 编程语言:cpp
- 解法介绍:ac自动机,对每个trie的无效节点赋值下一跳。
struct TrieNode {
bool end;
TrieNode *fail, *children[26];
TrieNode(): end(false), fail(nullptr) {
memset(children, 0, sizeof(children));
}
};
class StreamChecker {
public:
TrieNode *root, *current;
StreamChecker(vector<string>& words): root(new TrieNode()), current(root) {
for (auto &word : words) {
TrieNode *node = root;
for (auto &c : word) {
int idx = c - 'a';
if (!node->children[idx]) node->children[idx] = new TrieNode();
node = node->children[idx];
}
node->end = true;
}
queue<TrieNode *> q;
for (int i = 0; i < 26; i++) {
if (root->children[i]) root->children[i]->fail = root, q.push(root->children[i]);
else root->children[i] = root;
}
while (q.size()) {
TrieNode *node = q.front();
q.pop();
node->end = node->end || node->fail->end;
for (int i = 0; i < 26; i++) {
if (node->children[i]) node->children[i]->fail = node->fail->children[i], q.push(node->children[i]);
else node->children[i] = node->fail->children[i];
}
}
}
bool query(char letter) {
current = current->children[letter - 'a'];
return current->end;
}
};
题解 2 - python
- 编辑时间:2023-03-24
- 执行用时:544ms
- 内存消耗:50.4MB
- 编程语言:python
- 解法介绍:同上。
from queue import Queue
class TrieNode:
def __init__(self) -> None:
self.end = False
self.fail = None
self.children: List[TrieNode] = [None] * 26
class StreamChecker:
def __init__(self, words: List[str]):
self.root = self.current = TrieNode()
for word in words:
node = self.root
for c in word:
idx = ord(c) - ord('a')
if not node.children[idx]:
node.children[idx] = TrieNode()
node = node.children[idx]
node.end = True
q = Queue()
self.root.fail = self.root
for i in range(26):
if self.root.children[i]:
self.root.children[i].fail = self.root
q.put(self.root.children[i])
else:
self.root.children[i] = self.root
while q.qsize():
node: TrieNode = q.get()
node.end = node.end or node.fail.end
for i in range(26):
if node.children[i]:
node.children[i].fail = node.fail.children[i]
q.put(node.children[i])
else:
node.children[i] = node.fail.children[i]
def query(self, letter: str) -> bool:
self.current = self.current.children[ord(letter) - ord('a')]
return self.current.end
题解 3 - rust
- 编辑时间:2023-03-24
- 执行用时:56ms
- 内存消耗:33.4MB
- 编程语言:rust
- 解法介绍:同上。
pub use std::{cell::RefCell, rc::Rc};
struct TrieNode {
end: bool,
fail: Option<Rc<RefCell<TrieNode>>>,
children: Vec<Option<Rc<RefCell<TrieNode>>>>,
}
impl TrieNode {
fn new() -> Rc<RefCell<Self>> {
Rc::new(RefCell::new(Self {
end: false,
fail: None,
children: vec![None; 26],
}))
}
}
struct StreamChecker {
root: Rc<RefCell<TrieNode>>,
current: Rc<RefCell<TrieNode>>,
}
impl StreamChecker {
fn new(words: Vec<String>) -> Self {
let root = TrieNode::new();
let current = root.clone();
for word in words {
let mut node = root.clone();
for c in word.chars() {
let idx = c as usize - 'a' as usize;
let node_ref = node.as_ref();
{
let mut node = node_ref.borrow_mut();
if node.children[idx].is_none() {
node.children[idx] = Some(TrieNode::new());
}
}
let next_node = node_ref.borrow().children[idx].clone().unwrap();
node = next_node;
}
node.as_ref().borrow_mut().end = true;
}
let mut q = std::collections::VecDeque::<Rc<RefCell<TrieNode>>>::new();
{
let mut root_ref = root.as_ref().borrow_mut();
for i in 0..26 {
if root_ref.children[i].is_some() {
q.push_back(root_ref.children[i].clone().unwrap());
root_ref.children[i]
.clone()
.unwrap()
.as_ref()
.borrow_mut()
.fail = Some(root.clone());
} else {
root_ref.children[i] = Some(root.clone());
}
}
}
while !q.is_empty() {
let node = q.pop_front().unwrap();
{
let node = node.as_ref();
let end = node.borrow().end;
node.borrow_mut().end =
end || node.borrow().fail.as_ref().unwrap().as_ref().borrow().end;
}
for i in 0..26 {
let node = node.as_ref();
let fail_node = node
.borrow()
.fail
.as_ref()
.unwrap()
.as_ref()
.borrow()
.children[i]
.clone();
if node.borrow().children[i].is_some() {
q.push_back(node.borrow().children[i].clone().unwrap());
let child = node.borrow().children[i].clone().unwrap();
child.as_ref().borrow_mut().fail = fail_node.clone();
} else {
node.borrow_mut().children[i] = fail_node.clone();
}
}
}
Self { root, current }
}
fn query(&mut self, letter: char) -> bool {
let current = self.current.as_ref();
let next = current.borrow().children[letter as usize - 'a' as usize]
.as_ref()
.unwrap()
.clone();
self.current = next;
self.current.as_ref().borrow().end
}
}