刚学AC自动机,有几个问题不太明白,求大佬解惑
  • 板块灌水区
  • 楼主Patronus
  • 当前回复3
  • 已保存回复3
  • 发布时间2023/11/23 10:17
  • 上次更新2023/11/23 15:59:32
查看原帖
刚学AC自动机,有几个问题不太明白,求大佬解惑
533297
Patronus楼主2023/11/23 10:17
  1. AC自动机用拓扑排序优化的原理是什么?
  2. 下面代码中的 visvis 和 revrev 数组的作用是什么?
  3. 为什么一个节点的 endend 标记要记录第一个在此节点结束的模式串的编号?
  4. queryquery 的作用是不是把文本串的每个字符在字典树上打上标记?如果是的话,那假如文本串的长度比所有的模式串的都长,那文本串最后的字符是不是就无法在字典树中遍历到了?

十分感谢各位大佬能帮我解惑。

下面代码是 P5357 【模板】AC 自动机(二次加强版)

#include<bits/stdc++.h>
using namespace std;
const int N=4e6+5;
char s[N];
int n,cnt,indeg[N],vis[N],rev[N],ans;
queue<int>q;
struct node{
    int son[26];
    int end,fail;
    int ans;
}t[N];
void Insert(char *s,int id){
    int x=0,len=strlen(s);
    for(int i=0;i<len;i++){
        //printf("%d ",x);
        int ch=s[i]-'a';
        if(t[x].son[ch]==0){
            t[x].son[ch]=++cnt;
        }
        x=t[x].son[ch];
    }
    if(!t[x].end) t[x].end=id;
    rev[id]=t[x].end;
    return;
}
void get_fail(){
    for(int i=0;i<26;i++){
       if(t[0].son[i]) q.push(t[0].son[i]);
    }
    while(!q.empty()){
        int x=q.front();
        //printf("%d ",x);
        q.pop();
        int Fail=t[x].fail;
        for(int i=0;i<26;i++){
            int &y=t[x].son[i];
            if(!y){
                y=t[Fail].son[i];
                continue;
            }
            t[y].fail=t[Fail].son[i];
            indeg[t[Fail].son[i]]++;
            q.push(y);
        }
    }
}
void query(char *s){
    int x=0,len=strlen(s);
    for(int i=0;i<len;i++){
        int ch=s[i]-'a';
        x=t[x].son[ch];
        t[x].ans++;
    }
}
void topsort(){
    for(int i=0;i<=cnt;i++){
        if(!indeg[i]) q.push(i);
    }
    while(!q.empty()){
        int x=q.front();
        //printf("%d ",x);
        q.pop();
        vis[t[x].end]=t[x].ans;
        int y=t[x].fail;
        t[y].ans+=t[x].ans;
        indeg[y]--;
        if(!indeg[y]) q.push(y);
    }
}
int main(){
    //freopen(Name ".in", "r", stdin);
    //freopen(Name ".out", "w", stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%s",s);
        Insert(s,i);
    }
    get_fail();
    scanf("%s",s); query(s);
	topsort();
    //printf("%d\n",cnt);
    for(int i=1;i<=n;i++){
        printf("%d\n",vis[rev[i]]);
    }
    return 0;
}
2023/11/23 10:17
加载中...