bzoj 2780 [Spoj]8093 Sevenk Love Oimaster

LINK:Sevenk Love Oimaster

询问一个模式串在多少个文本串中出现过。

考虑广义SAM 统计这种数量问题一般有三种做法。

一种 暴力bitset 这道题可能可以过?

一种 暴力跳parent 复杂度多乘根号。

一种 线段树合并 乘个log.

最简便的 不容易T的首选第二种方法。

const int MAXN=100010<<1;
int n,m;
int last=1,cnt=1;
int vis[MAXN],sum[MAXN];
char a[MAXN];
struct wy
{
	int ch[26];
	int fa,len;
}t[MAXN];
inline int insert(int x)
{
	int p=last;
	if(t[p].ch[x])
	{
		int q=t[p].ch[x];
		if(len(q)==len(p)+1)return last=q;
		int nq=++cnt;
		t[nq]=t[q];
		vis[nq]=vis[q];sum[nq]=sum[q];
		len(nq)=len(p)+1;
		f(q)=nq;
		while(p&&t[p].ch[x]==q)
		{
			t[p].ch[x]=nq;
			p=f(p);
		}
		return last=nq;
	}
	int np=last=++cnt;
	len(np)=len(p)+1;
	while(p&&!t[p].ch[x])
	{
		t[p].ch[x]=np;
		p=f(p);
	}
	if(!p)f(np)=1;
	else
	{
		int q=t[p].ch[x];
		if(len(q)==len(p)+1)f(np)=q;
		else
		{
			int nq=++cnt;
			t[nq]=t[q];
			len(nq)=len(p)+1;
			f(np)=f(q)=nq;
			vis[nq]=vis[q];sum[nq]=sum[q];
			while(p&&t[p].ch[x]==q)
			{
				t[p].ch[x]=nq;
				p=f(p);
			}
		}
	}
	return last;
}
int main()
{
	freopen("1.in","r",stdin);
	gt(n);gt(m);
	rep(1,n,i)
	{
		gc(a);last=1;
		int len=strlen(a+1);
		rep(1,len,j)
		{
			insert(a[j]-'a');
			int w=last;
			while(w&&vis[w]!=i)vis[w]=i,++sum[w],w=f(w);
		}
	}
	rep(1,m,i)
	{
		gc(a);int p=1;
		int len=strlen(a+1);
		rep(1,len,j)p=t[p].ch[a[j]-'a'];
		put(sum[p]);
	}
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/chdy/p/12551126.html
今日推荐