// queue: 一个队列,保存节点指针 // root: 根节点 // 将根节点的fail指针设为null,并将其所有子节点入队 root->fail = null for p in root.childs: queue.push(p) // 层序遍历tire树 while !queue.empty(): // 对当前节点,先将其fail值默认为root cur = queue.pop(); cur->fail = root for p in cur.childs: queue.push(p) // 寻找其父节点的fail指针指向的节点的子节点 // 找到的第一个与当前节点值相同的节点就是当前节点的最长后缀节点 // 若没有相应的子节点,则迭代寻找fail的fail指针指向的节点。 fail = cur->parent->fail while fail != null and cur->fail == root: for p in fail.childs: if p->value == cur->value: cur->fail = p fail = fail->fail
// str:待匹配串 // root:自动机根节点 // 令cur指向根节点,并对str逐位匹配 cur = root for i in (0, str.length()): // 如果当前节点不存在str[i]对应的子节点,则进入cur->fail // 循环直到存在对应节点或到达根节点 auto index = Node::get_index(str[i]) while cur->childs[index] == nullptr && cur != root : cur = cur->fail // 如果仍没有对应节点,则退出此轮循环 if cur->childs[index] == nullptr : continue // 进入到对应节点中,同时使用temp遍历该节点的所有后缀 // 将路径上的所有接受节点对应模式出现次数+1 cur = cur->childs[index] temp = cur while temp != nullptr : for p in temp->patterns : ++nums[p] temp = temp->fail
voidmatch(const string& str){ auto cur = root; int i = 0; while (i < str.length()) { auto index = Node::get_index(str[i]); while (cur->childs[index] == nullptr && cur != root) { cur = cur->fail; } ++i; if (cur->childs[index] == nullptr) continue; cur = cur->childs[index]; auto temp = cur; while (temp != nullptr) { for (auto p : temp->patterns) { ++nums[p]; } temp = temp->fail; } } }
Node *root; vector<int> nums; voidgenerate_tire(const vector<string> &patterns){ for (int i = 0; i < patterns.size(); ++i) { auto cur = root; for (auto c : patterns[i]) { auto index = Node::get_index(c); if (cur->childs[index] == nullptr) { cur->childs[index] = newNode(cur); cur->childs[index]->value = c; } cur = cur->childs[index]; } cur->patterns.push_back(i); } }
voidgenerate_fails(){ queue<Node*> q; root->fail = nullptr; for (int i = 0; i < 26; ++i) { if (root->childs[i]) q.push(root->childs[i]); } while (!q.empty()) { auto cur = q.front(); q.pop(); cur->fail = root;
for (int i = 0; i < 26; ++i) { if (cur->childs[i]) q.push(cur->childs[i]); }
auto f = cur->parent->fail; while (f != nullptr && cur->fail == root) { auto index = Node::get_index(cur->value); if (f->childs[index]) { cur->fail = f->childs[index]; } f = f->fail; } } // while !q.empty } // generate_fails };