1. 程式人生 > >【BZOJ2780】[Spoj]8093 Sevenk Love Oimaster 廣義後綴自動機

【BZOJ2780】[Spoj]8093 Sevenk Love Oimaster 廣義後綴自動機

當前 named ostream number 一個點 urn mil ios abc

【BZOJ2780】[Spoj]8093 Sevenk Love Oimaster

Description

Oimaster and sevenk love each other.

But recently,sevenk heard that a girl named ChuYuXun was dating with oimaster.As a woman‘s nature, sevenk felt angry and began to check oimaster‘s online talk with ChuYuXun. Oimaster talked with ChuYuXun n times, and each online talk actually is a string.Sevenk asks q questions like this, "how many strings in oimaster‘s online talk contain this string as their substrings?"

Input

There are two integers in the first line, the number of strings n and the number of questions q.And n lines follow, each of them is a string describing oimaster‘s online talk. And q lines follow, each of them is a question.n<=10000, q<=60000 the total length of n strings<=100000, the total length of q question strings<=360000

Output

For each question, output the answer in one line.

Sample Input

3 3
abcabcabc
aaa
aafe
abc
a
ca

Sample Output

1
3
1

題意:給你一堆文本串,每次詢問一個串在多少個文本串中出現過。

題解:多串匹配要用到廣義SAM。就是在每當開始加入一個串的時候,將last指針變回root。

那麽這題怎麽搞?我們需要知道SAM中的每個節點被多少個文本串所包含。記錄sum[i]表示i被多少個文本串包含,vis[i]表示當前時刻,最後一個包含i的文本串是哪個。在建完SAM後,我們將所有串在SAM上再跑一邊,將經過的點,以及它的parent樹上的所有祖先都更新一遍(因為一個點被影響後它的所有parent也要被影響),如果某個點的vis=當前時間,則退出,否則更新sum和vis。

時間復雜度我不太會證,大概O(nsqrt(n))吧?不過這題也有O(nlogn)的做法,就是求出parent樹的DFS序,每次詢問相當於問一個點在parent樹的子樹中有多少個不同的文本串,也就轉換成在DFS序上的一段區間中有多少個不同的文本串。這個顯然是HH的項鏈啊,不過感覺好麻煩。(懶)

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int n,m,tot;
int pre[400010],ch[400010][26],mx[400010],s[400010],vis[400010],lp[400010],rp[400010];
char str[800010];
void updata(int x,int y)
{
	for(;x&&vis[x]!=y;x=pre[x])	s[x]++,vis[x]=y;
}
int extend(int x,int y,int p)
{
	int np=++tot;
	mx[np]=mx[p]+1;
	for(;p&&!ch[p][x];p=pre[p])	ch[p][x]=np;
	if(!p)	pre[np]=1;
	else
	{
		int q=ch[p][x];
		if(mx[q]==mx[p]+1)	pre[np]=q;
		else
		{
			int nq=++tot;
			pre[nq]=pre[q],pre[np]=pre[q]=nq,mx[nq]=mx[p]+1;
			memcpy(ch[nq],ch[q],sizeof(ch[q]));
			for(;p&&ch[p][x]==q;p=pre[p])	ch[p][x]=nq;
		}
	}
	return np;
}
int main()
{
	scanf("%d%d",&n,&m);
	int i,j,a,b;
	tot=1;
	for(i=1;i<=n;i++)
	{
		lp[i]=rp[i-1];
		scanf("%s",str+lp[i]);
		rp[i]=strlen(str);
		for(b=1,j=lp[i];j<rp[i];j++)	b=extend(str[j]-‘a‘,i,b);
	}
	for(i=1;i<=n;i++)
		for(a=1,j=lp[i];j<rp[i];j++)	a=ch[a][str[j]-‘a‘],updata(a,i);
	for(i=1;i<=m;i++)
	{
		scanf("%s",str);
		a=strlen(str);
		for(b=1,j=0;j<a;j++)
		{
			if(ch[b][str[j]-‘a‘])	b=ch[b][str[j]-‘a‘];
			else	break;
		}
		if(j==a)	printf("%d\n",s[b]);
		else	printf("0\n");
	}
	return 0;
}

【BZOJ2780】[Spoj]8093 Sevenk Love Oimaster 廣義後綴自動機