概要
文字列探索アルゴリズム。
ある文字列 \(T\) について、 \(N\) 個の文字列 \(s_1, s_2, ..., s_N\) の中からマッチする(最長の)文字列を線形に探索することができる。
計算量
\(O(|T| + \sum_i |s_i|)\)
実装
Python版 がベース
#include<string>
#include<queue>
using namespace std;
#define NN 30
struct TrieNode {
TrieNode(int size) : sz(size), cnt(0) {
for(int i = 0; i < NN; ++i) next[i] = nullptr;
suffix = nullptr;
}
TrieNode *next[NN];
TrieNode *suffix;
int sz, cnt;
};
TrieNode *root = new TrieNode(0);
void add(string s) {
TrieNode *node = root;
for(int i = 0; i < s.length(); ++i) {
int code = s[i] - 'a';
if(!node->next[code]) {
node = node->next[code] = new TrieNode(node->sz + 1);
} else {
node = node->next[code];
}
}
node->cnt = 1;
}
void suffix() {
queue<TrieNode*> que;
que.push(root);
while(!que.empty()) {
TrieNode* v = que.front(); que.pop();
for(int i = 0; i< NN; ++i) {
if(v->next[i] && v->sz < v->next[i]->sz) {
if(v->suffix) {
v->next[i]->suffix = v->suffix->next[i];
} else {
v->next[i]->suffix = root;
}
que.push(v->next[i]);
} else {
if(v->suffix) {
v->next[i] = v->suffix->next[i];
} else {
if(root->next[i]) {
v->next[i] = root->next[i];
} else {
v->next[i] = root;
}
}
}
}
}
root->suffix = root;
}
Verified
-
AtCoder: "JAG Practice Contest for ACM-ICPC Asia Regional 2017 - H問題: Separate String": source (C++14, 396ms)