【字符串】hdu5384

裸的ac自动机居然没有看出来。。。

于是乎手撕了一发,

话说果然还是不喜欢用模板,

这篇挂出来就当是以后自己ac自动机的写法了。

挺好看的。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
char s[200100],w_s[200100],tmp_s[200100];
int q[200100],q_tail,q_head,s_tail,s_len[200100],tot;
struct rec
{
	int next[30];
	int fail,count;	
}tree[100100];
void clear(int x)
{
	for (int i=1;i<=27;i++)
		tree[x].next[i]=-1;
	tree[x].count=0;
	tree[x].fail=0;
}
void insert(char a[])
{
	int len=strlen(a);
	int i,j,now=0,tmp;
	for (int i=0;i<len;i++)
	{
		tmp=a[i]-'a'+1;
		if (tree[now].next[tmp]==-1)
		{
			tree[now].next[tmp]=++tot;
			clear(tot);
		}
		now=tree[now].next[tmp];
	}
	tree[now].count++;
}
void makefail()
{
	int now,now_f;
	q_tail=q_head=0;
	for (int i=1;i<=26;i++)
		if (tree[0].next[i]!=-1)
		{
			q[++q_tail]=tree[0].next[i]; 
		}
	while (q_tail!=q_head)
	{
		q_head++;
		now=q[q_head];
		for (int i=1;i<=26;i++)
		{
			if (tree[now].next[i]!=-1)
			{
				q_tail++;
				q[q_tail]=tree[now].next[i];
				now_f=tree[now].fail;
				while (now_f>0&&tree[now_f].next[i]==-1)
					now_f=tree[now_f].fail;
				if (tree[now_f].next[i]!=-1) 
					now_f=tree[now_f].next[i];
				tree[tree[now].next[i]].fail=now_f; 
			}
		}
	}
}
void ac_work(char a[],int len)
{
	int tmp=0,ans=0,p;	
	for (int i=1;i<=len;i++)
	{
		int now=a[i]-'a'+1;
		while (tmp>0&&tree[tmp].next[now]==-1) tmp=tree[tmp].fail;
		if (tree[tmp].next[now]!=-1)
		{
			tmp=tree[tmp].next[now];
			p=tmp;
			while (p>0)
			{
				ans+=tree[p].count;
				p=tree[p].fail;
			}
		} 
	} 
	printf("%d\n",ans);
}
int main()
{
	freopen("test.in","r",stdin);
	freopen("test.out","w",stdout);
	int t,n,m;
	scanf("%d",&t);
	s_tail=0;
	while (t--)
	{
		tot=0;
		clear(0);
		s_tail=0;
		scanf("%d%d",&n,&m);
		for (int i=1;i<=n;i++)
		{
			scanf("%s",tmp_s);
			int tmp_len=strlen(tmp_s);
			s_len[i]=tmp_len;
			for (int j=1;j<=tmp_len;j++)
				s[s_tail+j]=tmp_s[j-1];
			s_tail+=tmp_len;
		}
		for (int i=1;i<=m;i++)
		{
			scanf("%s",tmp_s);
			insert(tmp_s); 
		}
		makefail();
		s_tail=1;
		for (int i=1;i<=n;i++)
		{
			for (int j=s_tail;j<=s_tail+s_len[i]-1;j++)
				w_s[j-s_tail+1]=s[j];
			s_tail+=s_len[i];
			ac_work(w_s,s_len[i]); 
		}
	} 
	return 0; 
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值