--- tags: codebook --- {%hackmd theme-dark %} # AC automaton ## 範例 ```graphviz digraph main{ node[fontcolor = white;color=white] edge[color=white;fontcolor=white] bgcolor = "#343434" subgraph null{ node[color=gray;style=dashed;label=nul] nul1 nul2 nul3 nul4 nul5 nul6 } subgraph str{ node[color=yellow] aa aaaa aba b baa } /* subgraph sign{ node[style=invis;] ex1 ex2 ex3 ex4 ex1->ex2[color=red;style=dashed;label="failure"] ex2->ex3[color=aquamarine;style=dashed;label="dictionary"] ex4[style=solid;label="pattern";color=yellow] }*/ root->a[label=" a"] root->b[label=" b"] a->aa[label=" a";] a->ab[label=" b"] b->ba[label=" a"] ab->aba[label=" b"] aa->aaa[label=" a"] aaa->aaaa[label=" a"] ba->baa[label=" a"] // {rank=max;newrank=true;ex1 ex2 ex3 ex4} {rank=same;root nul1} {rank=same;a b} {rank=same;aa ab ba} {rank=same;aba baa aaa} subgraph fail{ edge[color=red;style=dashed] root->nul1 {a b}->root {aa ba}->a {aaa baa}->aa aaaa->aaa aba->ba ab->b } subgraph dictionary{ edge[color=aquamarine;style=dashed] root->nul a->nul2 aa->nul3 b->nul4 ba->nul5 aba->nul6 ab->b {baa aaa aaaa}->aa } } ``` ## 範例程式碼 ```cpp= #include<iostream> #include<iomanip> #include<vector> using namespace std; struct automaton { vector<string> data; struct node { string *data; node *fail, *dic, *next[128]; //initialization node(): data(nullptr), next{} { fail = dic = nullptr; } }*root; void build(node* cur) { if (!cur) return; for (size_t i = 0; i != 128; i++) { if (!cur->next[i]) continue; //build failure_suffix path node* tmp = cur->fail; while (tmp && !tmp->next[i]) tmp = tmp->fail; cur->next[i]->fail = tmp ? tmp->next[i] : root; //build dictionary_suffix path tmp = cur->next[i]->fail; cur->next[i]->dic = tmp->data ? tmp : tmp->dic; build(cur->next[i]); } } vector<pair<string&, size_t>> operator()(const string& s) { vector<pair<string&, size_t>> v; node* cur = root; for (const auto& i : s) { //search by failure_suffix path while (cur && !cur->next[size_t(i)]) cur = cur->fail; cur = cur ? cur->next[size_t(i)] : root; //search by dictionary_suffic path for (node* tmp = cur; tmp; tmp = tmp->dic) if (tmp->data) v.emplace_back(*tmp->data, &i - &s.front() - tmp->data->size() + 1); } return v; } automaton(const vector<string>& v): data(v), root(new node) { //build trie for (auto& i : data) { node* cur = root; for (const auto& j : i) { if (!cur->next[size_t(j)]) cur->next[size_t(j)] = new node; cur = cur->next[size_t(j)]; } cur->data = &i; } //build path build(root); } }; ostream& operator<<(ostream& os, const vector<pair<auto, auto>>& v) { for (const auto& i : v) os << setw(5) << i.first << ' ' << setw(2) << i.second << endl; return os; } int main() { string tmp; vector<string> vec{"aa", "aaaa", "aba", "b", "baa"}; automaton t(vec); cout << t("aaaababaa") << endl; return 0; } ```