Light OJ Substring Frequency (II)

1427 - Substring Frequency (II)
Time Limit: 5 second(s) Memory Limit: 128 MB

A string is a finite sequence of symbols that are chosen from an alphabet. In this problem you are given a string T and n queries each with a string Pi, where the strings contain lower case English alphabets only. You have to find the number of times Pi occurs as a substring of T.

Input

Input starts with an integer T (≤ 10), denoting the number of test cases.

Each case starts with a line containing an integer n (1 ≤ n ≤ 500). The next line contains the string T (1 ≤ |T| ≤ 106). Each of the next n lines contains a string Pi (1 ≤ |Pi| ≤ 500).

Output

For each case, print the case number in a single line first. Then for each string Pi, report the number of times it occurs as a substring of T in a single line.

Sample Input

Output for Sample Input

2

5

ababacbabc

aba

ba

ac

a

abc

3

lightoj

oj

light

lit

Case 1:

2

3

1

4

1

Case 2:

1

1

0


分析:AC自动机模版

#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
char str[1000002];
char s[502][502];
int tot,cnt;
struct trie{
	int flag,fail,next[26],index;
	void init(){
		flag=0;fail=index=-1;
		for(int i=0;i<26;i++)next[i]=0;
	}
}q[500002];
void insert(char *S){
	int t=0,i=0,c;
	while(S[i]){
		c=S[i]-'a';
		if(!q[t].next[c]){
			q[++tot].init();
			q[t].next[c]=tot;
		}
		t=q[t].next[c];
		i++;
	}
	q[t].flag=1;
	q[t].index=cnt;
}
void get_fail(){
	int i;
	queue<int> Q;
	Q.push(0);
	while(!Q.empty()){
		int p=Q.front();Q.pop();
		for(i=0;i<26;i++){
			if(q[p].next[i]){
				int a=q[p].fail,b=q[p].next[i];
				while(a!=-1&&!q[a].next[i]) a=q[a].fail;
				if(a==-1) q[b].fail=0;
				else q[b].fail=q[a].next[i];
				Q.push(b);
			}
		}
	}
}
int ans[502];
void match(){
	int c,i=0,p,t=0;
	while(str[i]){
		c=str[i]-'a';
		p=t;
		while(p!=-1&&!q[p].next[c]) p=q[p].fail;
		if(p==-1) t=0;
		else t=q[p].next[c];
		p=t;
		while(p!=0){
			ans[q[p].index]+=q[p].flag;
			//q[p].flag=0;
			p=q[p].fail;
		}
		i++;
	}
	int j;
	for(i=0;i<cnt;i++){
		if(ans[i]>0)printf("%d\n",ans[i]);
		else {
			for(j=0;j<cnt;j++)
				if(i!=j&&strcmp(s[i],s[j])==0&&ans[j]>0) {printf("%d\n",ans[j]);break;}
			if(j==cnt)puts("0");
		}
	}
}
int main(){
	int t,n,ca;
	scanf("%d",&t);
	for(ca=1;ca<=t;ca++){
		scanf("%d",&n);
		scanf("%s",str);
		tot=0;q[0].init();
		cnt=0;
		while(n--){
			scanf("%s",s[cnt]);
			insert(s[cnt]);
			cnt++;
		}
		printf("Case %d:\n",ca);
		get_fail();
		memset(ans,0,sizeof(ans));
		match();
	}
	return 0;
}


 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值