社区讨论

为什么额外调用init()函数反而跑得更快

P5357【模板】AC 自动机参与者 2已保存回复 2

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
2 条
当前快照
1 份
快照标识符
@min8n63l
此快照首次捕获于
2025/12/01 22:22
3 个月前
此快照最后确认于
2025/12/03 22:05
3 个月前
查看原帖
rt, 38行在 insert() 里调用 init() 反而跑得快了 0.5 秒左右是什么玄学情况
pZZib7D.png
CPP
#include <bits/stdc++.h>
template <typename T>inline void read(T& aim){T num=0,f=1;int ch=getchar();for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'&&ch<='9';ch=getchar())num=num*10+ch-'0';aim=num*f;}
template <typename T>inline void write(T x){static int sta[40];int top=0;if(!x){putchar('0');return;}if(x<0)putchar('-'),x=-x;while(x)sta[++top]=x%10,x/=10;while(top)putchar(sta[top--]+'0');}
template <typename T>inline void print(T x,char ch='\n'){write(x);putchar(ch);}
inline void nl(){putchar('\n');}
template <typename T>inline void gmin(T& a,T b){if(a>b)a=b;}
template <typename T>inline void gmax(T& a,T b){if(a<b)a=b;}
template <typename T>inline T lowb(T x){return x&(-x);}
using namespace std;
typedef long long ll;
#define int long long
typedef pair<int,int> pii;
const int N=2e5+9,Sz=N;


namespace ac{
	struct node{
		int son[26],ans,fail,du,idx;
		void init(){
			memset(son,0,sizeof son);
			ans=fail=idx=0;
		}
	}tr[Sz];
	int tot,ans[N],pidx;
	void init(){
		tot=pidx=0;
		tr[0].init();
	}
	void insert(char *s,int &idx){
		int p=0;
		for(int i=1;s[i];i++){
			int &son=tr[p].son[s[i]-'a'];
			if(!son)son=++tot,tr[son].init();//??faster 
			p=son;
		}
		if(!tr[p].idx)tr[p].idx=++pidx;
		idx=tr[p].idx;
	}
	void build(){
		queue<int>q;
		for(int i=0;i<26;i++){
			if(tr[0].son[i])q.push(tr[0].son[i]);
		}
		while(!q.empty()){
			int x=q.front();q.pop();
			for(int i=0;i<26;i++){
				if(tr[x].son[i]){
					tr[tr[x].son[i]].fail=tr[tr[x].fail].son[i];
					tr[tr[tr[x].fail].son[i]].du++;
					q.push(tr[x].son[i]);
				}
				else{
					tr[x].son[i]=tr[tr[x].fail].son[i];
				}
			}
		}
	}
	void query(char *s){
		int p=0;
		for(int i=1;s[i];i++){
			p=tr[p].son[s[i]-'a'];
			tr[p].ans++;
		}
	}
	void topu(){
		queue<int>q;
		for(int i=0;i<=tot;i++){
			if(tr[i].du==0)q.push(i);
		}
		while(!q.empty()){
			int x=q.front();q.pop();
			ans[tr[x].idx]=tr[x].ans;
			int y=tr[x].fail;
			tr[y].ans+=tr[x].ans;
			if(!--tr[y].du)q.push(y);
		}
	}
}

int n,idx[N];
char s[N*10];
signed main(){
	ac::init();
	read(n);
	for(int i=1;i<=n;i++){
		scanf("%s",s+1);
		ac::insert(s,idx[i]);
		ac::ans[i]=0;
	}
	ac::build();
	scanf("%s",s+1);
	ac::query(s);
	ac::topu();
	for(int i=1;i<=n;i++){
		print(ac::ans[idx[i]]);
	}

	
	return 0;
}

回复

2 条回复,欢迎继续交流。

正在加载回复...