洛谷 P3808 【模板】AC自动机(简单版)

 

AC 自动机模板题 

不做详细解释,但是强调几个代码中需要注意到的地方

  • AC 自动机第一步利用字典树将模式串放入树中
  • 第二步利用 BFS 构建 fail 指针,构造 fail 指针时需要注意,构建节点 u(x 代表节点 u 中的字母) 的 fail 指针时,是在其父节点位置时构造的,当 x 存在时,其 fail 指针指向其父节点 fail 指针中的 x 节点;而当 x 不存在时,只要将 u 指向其父节点 fail 指针中的 x 节点,这样可以在后续查找当中从字典树的底部跳到树顶(不明白的仔细想一下第三步的查询过程)
  • 第三步查询时,对于每一个节点来说,如果其子节点没有与之匹配的,那么沿着失配边走直到找到是否有匹配的
const int N=1e6+5;

    int n,m;
    int i,j,k;
    char s[N];
    int f[N];
    int t[N][26],tot=0;
    int vis[N];

int idx(char ch){ return  ch-'a'; }

void insert(char *s)
{
	int rt=0;
	for(int i=0;s[i];i++){
		int x=idx(s[i]);
		if(!t[rt][x]) t[rt][x]=++tot;
		rt=t[rt][x];
	}
	vis[rt]++;
}

void build()
{
	queue<int> q;
	for(int i=0;i<26;i++) if(t[0][i]) f[t[0][i]]=0,q.push(t[0][i]);
	while(q.size()){
		int u=q.front(); q.pop();
		for(int i=0;i<26;i++) {
			if(t[u][i]) f[t[u][i]]=t[f[u]][i],q.push(t[u][i]);
			else t[u][i]=t[f[u]][i];
		}
	}
}

int query(char *s)
{
	int rt=0,ans=0;
	for(int i=0;s[i];i++){
		int x=idx(s[i]);
		rt=t[rt][x];
		for(int u=rt;u && vis[u]!=-1;u=f[u]) ans+=vis[u],vis[u]=-1;
	}
	return ans;
}

int main()
{
    //IOS;
    while(~sd(n)){
    	for(int i=1;i<=n;i++) ss(s),insert(s);
    	build();
    	ss(s);
    	int ans=query(s);
    	pd(ans);
    }
    return 0;
}

 

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页