zoukankan      html  css  js  c++  java
  • 【BZOJ1212】L语言(AC自动机)

    【BZOJ1212】L语言(AC自动机)

    题面

    BZOJ

    题解

    很自然的,既然要匹配单词,那就全部都丢到(AC)自动机里面去

    现在想想怎么匹配
    先是(AC)自动机正常的匹配
    如果此时这个位置能够匹配上一个串
    我们就需要判断一下这个串覆盖到这个文本串中
    它的前一位是否恰好被覆盖
    如果有的话
    我们也不能直接计算
    因为可能是其他不同的串拼起来的
    所以,就开一个数组差分
    表示当前位置可以匹配

    最后,对于每个文本串
    从前往后扫一遍差分数组
    直到有(0)的地方就直接输出就行啦

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    inline int read()
    {
    	int x=0,t=1;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return x*t;
    }
    struct Node
    {
    	int vis[26];
    	int dep,lst,fail;
    }t[5000];
    int n,m,tot;
    char s[2000000];
    int cc[2000000];
    bool vis[2000000];
    void insert(char *s)
    {
    	int l=strlen(s+1),now=0;
    	for(int i=1;i<=l;++i)
    	{
    		if(!t[now].vis[s[i]-97])
    			t[now].vis[s[i]-97]=++tot;
    		now=t[now].vis[s[i]-97];
    		t[now].dep=i;
    	}
    	t[now].lst=1;
    }
    void GetFail()
    {
    	queue<int> Q;
    	for(int i=0;i<26;++i)
    		if(t[0].vis[i])Q.push(t[0].vis[i]);
    	while(!Q.empty())
    	{
    		int u=Q.front();Q.pop();
    		for(int i=0;i<26;++i)
    			if(t[u].vis[i])
    				t[t[u].vis[i]].fail=t[t[u].fail].vis[i],Q.push(t[u].vis[i]);
    			else t[u].vis[i]=t[t[u].fail].vis[i];
    	}
    }
    int main()
    {
    	n=read();m=read();
    	for(int i=1;i<=n;++i)
    	{
    		scanf("%s",s+1);
    		insert(s);
    	}
    	GetFail();
    	while(m--)
    	{
    		scanf("%s",s+1);
    		int l=strlen(s+1);
    		int lst=0,now=0;
    		memset(cc,0,sizeof(cc));
    		memset(vis,0,sizeof(vis));
    		vis[0]=true;
    		for(int i=1;i<=l;++i)
    		{
    			now=t[now].vis[s[i]-97];
    			for(int j=now;j;j=t[j].fail)
    				if(t[j].lst&&vis[i-t[j].dep])
    				{
    					vis[i]=true;
    					cc[i-t[j].dep+1]++;
    					cc[i+1]--;
    				}
    		}
    		for(int i=1,tot=0;i<=l;++i)
    		{
    			tot+=cc[i];
    			if(tot)++lst;else break;
    		}
    		printf("%d
    ",lst);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    IEEE 754 浮点数的表示方法
    .NET Core 3.0及以上的EFCore连接MySql
    一些常见错误/技巧/结论总结
    2-sat学习笔记
    动态DP学习笔记
    动态规划优化算法——wqs二分 and 折线优化
    扩展莫队小总结(二) (回滚莫队/二次离线莫队)
    CF1504X Codeforces Round #712
    CF1500D Tiles for Bathroom (递推+大讨论)
    CF1486X Codeforces Round #703
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8313084.html
Copyright © 2011-2022 走看看