记录我的Sam模板

博客介绍了广义相关内容,一是边匹配边计算贡献时,父亲贡献直接算,当前点贡献用匹配长度算;二是若一个串需多次在sam上跑,可先跑完预处理匹配信息或直接建进广义sam。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

const int maxn = 100005;

struct Sam {
	int next[maxn << 1][26];
	int link[maxn << 1], step[maxn << 1];
	int a[maxn], b[maxn << 1];
	int sz, last, root;
	
	void init() {
		//如多次建立自动机,加入memset操作
		root = sz = last = 1;
		memset(next[root],0,sizeof(next[root]));
	}

	void add(int c) {
		int p = last;
		int np = ++sz;
		last = np;
		

		memset(next[np],0,sizeof(next[np]));
		step[np] = step[p] + 1;
		while(!next[p][c] && p) {
			next[p][c] = np;
			p = link[p];
		}

		if(p == 0) {
			link[np] = root;
		} else {
			int q = next[p][c];
			if(step[p] + 1 == step[q]) {
				link[np] = q;
			} else {
				int nq = ++sz;
				memcpy(next[nq], next[q], sizeof(next[q]));
				step[nq] = step[p] + 1;
				link[nq] = link[q];
				link[q] = link[np] = nq;
				while(next[p][c] == q && p) {
					next[p][c] = nq;
					p = link[p];
				}
			}
		}
	}

	void build() {
		init();
		for(int i = 0; s[i]; i++) {
			add(s[i] - 'a');
		}
		for(int i = 1; i <= sz; i++) {
			a[step[i]]++;
		}
		for(int i = 1; i <= step[last]; i++) {
			a[i] += a[i - 1];
		}
		for(int i = 1; i <= sz; i++) {
			b[a[step[i]]--] = i;
		}
	}
} sam;

广义:

	if(next[last][c] && step[last] + 1 == step[next[last][c]]) {
			last = next[last][c];
			return;
	}

*需要边匹配边计算贡献的时候,父亲的贡献直接算,当前点的贡献要用匹配长度来算
*如果一个串需要多次在sam上跑,可以先全部跑完预处理出匹配信息,或者直接建进广义sam

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值