版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
模板
class Aho_Corasick {
public:
static const int MAXN = 1e4*50+10;
int nxt[MAXN][26], fail[MAXN], end[MAXN];
int root, L;
Aho_Corasick ( ) { };
int newnode ( ) {
for ( int i = 0; i < 26; i++ )
nxt[L][i] = -1;
end[L++] = 0;
return L-1;
}
void init ( ) { // 先初始化
L = 0;
root = newnode ( );
}
void insert ( char buf[] ) { // 再插入多个模式串构成字典树
int len = strlen ( buf );
int now = root;
for ( int i = 0; i < len; i++ ) {
if ( nxt[now][buf[i] - 'a'] == -1 )
nxt[now][buf[i] - 'a'] = newnode ( );
now = nxt[now][buf[i] - 'a'];
}
end[now]++;
}
void build ( ) { // 然后给树建立失配指针
queue<int>Q;
fail[root] = root;
for ( int i = 0; i < 26; i++ )
if ( nxt[root][i] == -1 )
nxt[root][i] = root;
else {
fail[nxt[root][i]] = root;
Q.push ( nxt[root][i] );
}
while ( !Q.empty ( ) ) {
int now = Q.front ( );
Q.pop ( );
for ( int i = 0; i < 26; i++ )
if ( nxt[now][i] == -1 )
nxt[now][i] = nxt[fail[now]][i];
else {
fail[nxt[now][i]] = nxt[fail[now]][i];
Q.push ( nxt[now][i] );
}
}
}
long long query ( char buf[] ) { // 查询模式串在文本串出现次数前需要先构建 build 构建适配指针
int len = strlen ( buf ), now = root; long long res = 0;
for ( int i = 0; i < len; i++ ) {
now = nxt[now][buf[i] - 'a'];
int temp = now;
while ( temp != root ) {
res += end[temp];
end[temp] = 0;
temp = fail[temp];
}
}
return res;
}
}ac;