AC自动机

变量

  • int tr[p][i]\text{int}\ \texttt{tr[p][i]}:字典树中 pp 节点的字符映射为 ii 的儿子。
  • int tot\text{int}\ \texttt{tot}:字典树中节点的个数。
  • int e[p]\text{int}\ \texttt{e[p]}:字典树中以节点 pp 为结尾的模式串的个数。
  • int fail[p]\text{int}\ \texttt{fail[p]}:字典树中节点 pp 的失配指针。
  • queue< int > q\text{queue< int >}\ \texttt{q}:字典树中用于 bfs\text{bfs} 遍历的队列。

函数

  • void insert(string s)\text{void}\ \texttt{insert(string s)}:在自动机中插入模式字符串 ss
  • void build()\text{void}\ \texttt{build()}:建立自动机,一般在插入完模式字符串后使用。
  • int query(string t)\text{int}\ \texttt{query(string t)}:求匹配字符串 tt 的模式串的个数。

代码

struct AC{
	int tr[N][26],tot;
	int e[N],fail[N];
	queue<int>q;
	void insert(string s){
		int p=0;
		for(int i=0;i<s.size();i++){
			if(!tr[p][s[i]-'a'])
				tr[p][s[i]-'a']=++tot;
			p=tr[p][s[i]-'a'];
		}
		e[p]++;
	}
	void build(){
		for(int i=0;i<26;i++)
			if(tr[0][i])
				q.push(tr[0][i]);
		while(q.size()){
			int p=q.front();
			q.pop();
			for(int i=0;i<26;i++){
				if(tr[p][i]){
					fail[tr[p][i]]=tr[fail[p]][i];
					q.push(tr[p][i]);
				}
				else
					tr[p][i]=tr[fail[p]][i];
			}
		}
	}
	int query(string t){
		int p=0,ans=0;
		for(int i=0;i<t.size();i++){
			p=tr[p][t[i]-'a'];
			for(int j=p;j&&e[j]!=-1;j=fail[j]){
				ans+=e[j];
				e[j]=-1;
			}
		}
		return ans;
	}
}ac;
posted @ 2022-08-01 23:48  luckydrawbox  阅读(16)  评论(0)    收藏  举报  来源