ACオートマトン(対象C++実装)
9095 ワード
ACオートマトン(AC automatic)を使用して、TrieツリーTrieツリーとACオートマトンを組み合わせたデータ構造(複数のFailポインタのみ):
Trieツリーには、3つの基本演算ACオートマトンの挿入、検索、破棄が含まれています.Trieツリーの特性については、Failポインタ関数の構築とマルチモードマッチング関数の構築(Trieツリー実装、前の記事を参照)の意味用途がコード注釈に記載されています.
例:yasherhsでsay、she、shr、her、shに含まれる個数(sherとherの2つの単語を含む)を検索します.
出力:11111 3
class Trie{
private:
size_t count; //
size_t flag; //
Trie* fail; // AC Fail
Trie **next; //
};
Trieツリーには、3つの基本演算ACオートマトンの挿入、検索、破棄が含まれています.Trieツリーの特性については、Failポインタ関数の構築とマルチモードマッチング関数の構築(Trieツリー実装、前の記事を参照)の意味用途がコード注釈に記載されています.
#include"Trie.h"
#include // BFS Fail
class ACAutomatic
{
public:
explicit ACAutomatic(Trie *&_trie) : trie(_trie), typeCase(trie->typeCase) { makeFail(); }
ACAutomatic() = delete;
~ACAutomatic() = default;
/**
Fail :
C, , , C 。
C 。 root , root。
BFS( ), , 。
*/
void makeFail();
/**
root , 。
, , 。 root , , 。
AC , , , , 。
*/
int SearchACTrie(const std::string &strings) const;
private:
Trie *≜
TypeCase &typeCase;
std::queue trieQueue;
};
inline void ACAutomatic::makeFail()
{
auto root = trie;
trie->fail = trie;
trieQueue.push(trie);
while (trieQueue.size() != 0)
{
auto rootNode = this->trieQueue.front();
for (auto beg(0); beg < typeCase; ++beg) {
if (rootNode->next[beg]) {
trieQueue.push(rootNode->next[beg]);
if (rootNode->fail->next[beg] && rootNode->fail->next[beg] != rootNode->next[beg])
rootNode->next[beg]->fail = rootNode->fail->next[beg];
else rootNode->next[beg]->fail = rootNode->fail;
}
}
trieQueue.pop();
}
}
inline int ACAutomatic::SearchACTrie(const std::string &strings) const
{
auto strIteratorToInt(0);
auto triethis(trie);
auto cnt(0);//
std::string::const_iterator stringBegin(strings.begin());
std::string::const_iterator stringEnd(strings.end());
while (stringBegin != stringEnd)
{
switch (typeCase)
{
case 2: strIteratorToInt = static_cast(*stringBegin) - 48;//
if (strIteratorToInt < 0 || strIteratorToInt>1) return false;
break;
case 10:
strIteratorToInt = static_cast(*stringBegin) - 48;//
if (strIteratorToInt < 0 || strIteratorToInt>9) return false;
break;
case 26:strIteratorToInt = static_cast(*stringBegin) - 97;//
if (strIteratorToInt < 0 || strIteratorToInt>26) return false;
break;
default:return false;
}
if (triethis->next[strIteratorToInt]) {
triethis = triethis->next[strIteratorToInt];
if (triethis->flag)
cnt+= triethis->flag;
}
else {
triethis = triethis->fail;
if(triethis->next[strIteratorToInt])
triethis = triethis->next[strIteratorToInt];
if (triethis->flag)
cnt += triethis->flag;
}
++stringBegin;
}
return cnt;
}
例:yasherhsでsay、she、shr、her、shに含まれる個数(sherとherの2つの単語を含む)を検索します.
#include
#include"Trie.h"
#include"ACAutomatic.h"
int main()
{
auto trie = new Trie(LowerCase);// Trie ,
std::cout << trie->InsertTrie("say");// true
std::cout << trie->InsertTrie("she");// true
std::cout << trie->InsertTrie("shr");// true
std::cout << trie->InsertTrie("her");// true
std::cout << trie->InsertTrie("sh");// true
std::cout << std::endl;
auto acautomatic = new ACAutomatic(trie);// AC
std::cout<SearchACTrie("yasherhs");//
return 0;
}
出力:11111 3