HDU 4622 本质不同的子串个数:后缀自动机

题意:给出一个串,每次求一个子串[ l , r ]。问这个串中,本质不同的子串个数,多组询问,数据小。


题解:记住SAM是ON的。所以直接对每个[ l , r ]建SAM,然后建完就出答案。时间足够用。模板题为什么要写博客呢。。。。因为复用自动机的话。。要清空呀。。。。


Code:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e3+100;
char s[maxn];
int len;
int T;
struct SAM{
	int last,cnt,nxt[maxn*2][26],fa[maxn*2],l[maxn*2];
	int ans;
	void init(){
		last = cnt=1;
		memset(nxt[1],0,sizeof nxt[1]);
		fa[1]=0;ans=0;l[1]=0;
	}
	int inline newnode(){
		++cnt;
		memset(nxt[cnt],0,sizeof nxt[cnt]);
		fa[cnt]=l[cnt]=0;
		return cnt;
	}
	void add(int c){
		int p = last;
		int np = newnode();
		last = np;
		l[np] = l[p]+1;
		while (p&&!nxt[p][c]){
			nxt[p][c]=np;
			p = fa[p];
		}
		if (!p){
			fa[np]=1;
		}else{
			int q = nxt[p][c];
			if (l[q]==l[p]+1){
				fa[np] = q;
			}else{
				int nq = newnode();
				memcpy(nxt[nq],nxt[q],sizeof nxt[q]);
				fa[nq] = fa[q];
				l[nq] = l[p]+1;
				fa[np]=fa[q]=nq;
				while (nxt[p][c]==q){
					nxt[p][c]=nq;
					p=fa[p];
				}
			}
		}
//		cout<<fa[last]<<endl;
		ans+=l[last]-l[fa[last]];
	}
	void query(){
		int l,r;
		scanf("%d%d",&l,&r);
		init();
		for (int i=l;i<=r;i++){
//			cout<<s[i]<<" ";
			add(s[i]-'a');
		}
		printf("%d\n",ans);
	}
}sam;
int main(){
	scanf("%d",&T);
	while (T--){
		scanf("%s",s+1);
		int Q;
		scanf("%d",&Q);
		while (Q--){
			sam.query();
		}
	}
	return 0;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值