社区讨论

关于这题SAM被卡掉了的一档事

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

讨论操作

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

当前回复
6 条
当前快照
1 份
快照标识符
@locnsb8t
此快照首次捕获于
2023/10/30 16:49
2 年前
此快照最后确认于
2023/11/05 03:50
2 年前
查看原帖

关于这题SAM被卡掉了的一档事

请问一下诸位大佬,为什么SAM会被卡掉,而且还是内存被卡了。
SAM的理论复杂度是O(n)O(n),在这题就是:
3×2×S×4=48000000B=45MB 3 \times 2 \times |S| \times 4 = 48000000 B = 45 MB
然而却炸掉了,还是MLE,哪位大佬能来帮蒟蒻看一看,还是我对SAM的空间复杂度理解错了?
CPP
#include <bits/stdc++.h>
#include <string>
#include <vector>
using namespace std;
const int N=2e6+5,M=2e5+5,INIT=1;
struct state{
	int len,link;
	map <char,int> nxt;
}sam[N*2];
int siz,last,cnt[N*2],tag[N],n;
string str,ade,tmp;
vector <int> son[N*2];
void sam_init(){
	siz=1,last=INIT;
	sam[INIT].len=0;
	sam[INIT].link=0;
}
void sam_extend(char c){
	int cur=++siz,p=last;
	sam[cur].len=sam[last].len+1;
	cnt[cur]=1;
	while(p&&!sam[p].nxt.count(c)){
		sam[p].nxt[c]=cur;
		p=sam[p].link;
	}
	if(!p)sam[cur].link=INIT;
	else{
		int q=sam[p].nxt[c];
		if(sam[q].len==sam[p].len+1){
			sam[cur].link=q;
		}
		else{
			int clone=++siz;
			sam[clone]=sam[q];
			sam[clone].len=sam[p].len+1;
			while(p&&sam[p].nxt[c]==q){
				sam[p].nxt[c]=clone;
				p=sam[p].link;
			}
			sam[cur].link=sam[q].link=clone;
		}
	}
	last=cur;
}
void run(int u){
	for(int i=0;i<son[u].size();i++){
		run(son[u][i]);
		cnt[u]+=cnt[son[u][i]];
	}
}
int sam_run(string s){
	int len=s.size(),p=INIT;
	for(int i=0;i<len;i++){
		char c=s[i];
		if(!sam[p].nxt[c])return 0;
		else p=sam[p].nxt[c];
	}
	return cnt[p];
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		tag[i]=ade.size();
		cin>>tmp;
		ade+=tmp;
		
	}
	tag[n+1]=ade.size();
	cin>>str;
	sam_init();
	for(int i=0;i<str.size();i++){
		sam_extend(str[i]);
	}
	for(int i=1;i<=siz;i++){
		son[sam[i].link].push_back(i);
	}
	run(INIT);
	for(int i=1;i<=n;i++){
		int p=INIT,ans=0;
		for(int j=tag[i];j<tag[i+1];j++){
			char c=ade[j];
			if(!sam[p].nxt[c]){
				ans=-1;
				break;
			}
			p=sam[p].nxt[c];
		}
		if(ans==-1)printf("0\n");
		else printf("%d\n",cnt[p]);
	}
}

回复

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

正在加载回复...