算法模板:后缀自动机模板

pascal后缀自动机模板 

//后缀自动机模板
var
	i,last,q,p,total,x,cur,clo:longint;
	s:ansistring;
	n:int64;
	bz:boolean;
	len,link:array[0..150000]of longint;	//len——节点i到0的最短路,link——状态i的(来源?)
	son:array[0..150000,1..52]of longint;   //节点i的儿子
begin
	assign(input,'sf_suffixautomaton_template.in');reset(input);
	assign(output,'sf_suffixautomaton_template.out');rewrite(output);
	readln(s);
	readln(n);
	last:=0;
	for i:=1 to length(s) do
	begin
		if s[i]<='Z'then x:=ord(s[i])-64
		else x:=ord(s[i])-70;   //字符转ASCALL码
		inc(total);
		cur:=total;
		p:=last;
		len[cur]:=len[last]+1;  //新建节点cur,因其位置在后缀自动机中存储的原串上,所以len[cur]
								//永远为上一个cur(即last)的len+1
		bz:=false;
		while son[p,x]=0 do		//p是否有值为x的边
		begin
			if (p=0)and(son[p,x]=0) then
			begin
				son[p,x]:=cur;	//走到link链的底部,无法再走了,所以将连完边后将link[cur]赋为0
				link[cur]:=p;
				break;
			end;
			son[p,x]:=total;	//没边,便给p向cur连上一条值为x的边
			p:=link[p];			//走link链
			if son[p,x]<>0 then bz:=true;	//说明新的p节点有这条边了,退出,打标记是为了保证连完边
											//退出后不会误判
		end;
		if (p=0)and(son[p,x]=0) then	//迷之bug导致bz变为了true,于是多判一次
		begin
			son[p,x]:=cur;
			link[cur]:=p;
			bz:=false;
		end;
		if bz=true then
		begin
			q:=son[p,x];
			if len[q]=len[p]+1 then link[cur]:=q	//如果已有儿子len值合法则更新link[cur]
			else
			begin
				inc(total);	//否则克隆一个节点,其link值与son均与已有儿子相同
				clo:=total;
				link[clo]:=link[q];
				son[clo]:=son[q];
				len[clo]:=len[p]+1;	//但其len等于len[p]+1
				link[q]:=clo;		//将cur和q的link值改为clo
				link[cur]:=clo;
				while (son[p,x]=q)do	//将p的link链上(包括p点)的,连出的x边儿子为q的点的儿子更改为clo
				begin
					son[p,x]:=clo;
					if p=0 then break;
					p:=link[p];
				end;
			end;
		end;
		last:=cur;	//更新last
	end;
	close(input);
	close(output);
end.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值