HDU 6208 The Dominator of Strings AC自动机

本文介绍了一种使用AC自动机解决字符串匹配问题的方法,旨在判断一组字符串是否能在一条最长的母串中找到所有子串。通过构建自动机并利用失败指针加速匹配过程,确保了算法效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:长度最长串为母串 问其余n-1个串是否都能在母串中匹配 ,总字符长度<=1e5.

AC自动机匹配数为n则有解.

query时不重复统计以标记结点.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+20,M=1e5+5; 
struct AHO
{
	int chd[N][26],v[N],f[N],last[N],sz,ans;
	void init()
	{
		sz=1;ans=0;
		memset(v,0,sizeof(v));
		memset(f,0,sizeof(f));
		memset(chd[0],0,sizeof(chd[0]));
	}
	void insert(char *s)
	{
		int u=0,i=0;
		while(s[i])
		{
			int id=s[i]-'a';
			if(!chd[u][id])
			{
				memset(chd[sz],0,sizeof(chd[sz]));
				chd[u][id]=sz++;
			}
			u=chd[u][id];
			i++; 
		}
		v[u]++;
	}
	void getfails()
	{
		queue<int> q;
		f[0]=0;
		for(int c=0;c<26;c++)
		{
			int u=chd[0][c];
			if(u)
			{
				f[u]=0;
				q.push(u);last[u]=0;
			}
		}
		while(!q.empty())
		{
			int r=q.front();q.pop();
			for(int c=0;c<26;c++)
			{
				int u=chd[r][c];
				if(!u)
				{
					chd[r][c]=chd[f[r]][c];
				}
				else
				{
					q.push(u);
					int x=f[r];
				
					while(x&&!chd[x][c]) 
						x=f[x];
					f[u]=chd[x][c];
			
					last[u]=v[f[u]]? f[u]:last[f[u]];	
				}
			}
		}
	}
 	int find(char *s)
    {
        int u=0,cnt=0;
        int n=strlen(s);
        for(int i=0;i<n;i++)
        {
            int c=s[i]-'a';
            u=chd[u][c];
            int temp=0;//mark
            if(v[u])
                temp=u;
            else if(last[u])
                temp=last[u];
            while(temp)
            {
                cnt+=v[temp];
                v[temp]=0;
                temp=last[temp];
            }
        }
        return cnt;
    }
}aho;
char s[M],dic[M];
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		aho.init();
		int n,mx=0;
		scanf("%d",&n);
		for(int i=0;i<n;i++)
		{
			scanf("%s",dic);
			int tl=strlen(dic);
			if(mx<tl)
			{
				mx=tl;
				strcpy(s,dic);
			}
			aho.insert(dic);
		}
		aho.getfails();//
		int ans=aho.find(s);
		//printf("%d\n",ans);
		if(ans==n)
			printf("%s\n",s);
		else
			printf("No\n");
	}
	return 0;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值