struct AC {
int ans, total, val[MAXN], fail[MAXN];//ans保存题目解,total分配新节点,val存节点值,fail是失配指针
int child[MAXN][SIZE];
void init() {//使用ac自动机前务必初始化
ans = 0; total = 1;
memset(val, 0, sizeof(val));
memset(fail, 0, sizeof(fail));
memset(child[0], 0, sizeof(child[0]));
}
void Insert(const char *P) {//构造字典树
int root = 0;
for (int i = 0; P[i]; i++) {
if (!child[root][P[i] - 'a']) {
memset(child[total], 0, sizeof(child[total]));
child[root][P[i] - 'a'] = total++;
}
root = child[root][P[i] - 'a'];
}
val[root]++;
}
void Getfail() {//bfs构造fail指针
queue<int> q;
for (int i = 0; i < SIZE; i++) {//首先把root的所有儿子的fail指针都指向root
if (child[0][i]) q.push(child[0][i]);//因为节点的fail指针默认为root所以就简写了
}
while (!q.empty()) {
int root = q.front(); q.pop();
for (int i = 0; i < SIZE; i++) {
int u = child[root][i];
if (!u) { child[root][i] = child[fail[root]][i]; continue; }//Trie图优化,建立失配边
q.push(u);
int v = fail[root];
while (v && !child[v][i]) v = fail[v];//构造fail指针的关键,推荐画图辅助理解
fail[u] = child[v][i];
}
}
}
void Search(const char *T) {
Getfail();
int root = 0, temp;
for (int i = 0; T[i]; i++) {
temp = root = child[root][T[i] - 'a'];//因为经过了Trie图优化,所以这里只要沿着root走就可以
while (temp && val[temp]) {//遍历fail路径,防止遗漏
ans += val[temp];
val[temp] = 0;//防止重复统计,根据题目而定
temp = fail[temp];
}
}
}
}ac;
ac自动机模版
最新推荐文章于 2023-03-14 18:54:10 发布