zoukankan      html  css  js  c++  java
  • 洛谷P3796 【模板】AC自动机(加强版) AC自动机

    网址:https://www.luogu.org/problem/P3796

    题意:

    有$n$个由小写字母组成的模式串以及一个文本串$T$。每个模式串可能会在文本串中出现多次。你需要找出哪些模式串在文本串$T$中出现的次数最多。输入含多组数据。对于每组数据,第一行输出模式串最多出现的次数,接下去若干行每行输出一个出现次数最多的模式串,按输入顺序排列。

    题解:

    $AC$自动机板子题。和只寻找一次相比,取消路径上的已访问标记即可。

    AC代码:

    #include <iostream>
    #include <string>
    #include <map>
    #include <vector>
    #include <queue>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    #define maxn int(1e6+9)
    int trie[maxn][26];
    int cntword[maxn];
    int fail[maxn];
    int cnt = 0, strid = 0;
    struct stru
    {
    	int num, pos;
    };
    stru ans[200];
    vector<string>input;
    struct ac
    {
    	void insert(string& str)
    	{
    		int root = 0, next;
    		for (int i = 0; i < str.size(); ++i)
    		{
    			next = str[i] - 'a';
    			if (!trie[root][next])
    				trie[root][next] = ++cnt;
    			root = trie[root][next];
    		}
    		cntword[root] = ++strid;
    	}
    	void buildfail()
    	{
    		queue<int>que;
    		for (int i = 0; i < 26; ++i)
    			if (trie[0][i])
    			{
    				que.push(trie[0][i]);
    				fail[trie[0][i]] = 0;
    			}
    		while (!que.empty())
    		{
    			int now = que.front();
    			que.pop();
    			for (int i = 0; i < 26; ++i)
    			{
    				if (trie[now][i])
    				{
    					fail[trie[now][i]] = trie[fail[now]][i];
    					que.push(trie[now][i]);
    				}
    				else
    					trie[now][i] = trie[fail[now]][i];
    			}
    		}
    	}
    	void query(string& str)
    	{
    		int now = 0;
    		for (int i = 0; i < str.size(); ++i)
    		{
    			now = trie[now][str[i] - 'a'];
    			for (int j = now; j ; j = fail[j])
    			{
    				++ans[cntword[j]].num;
    			}
    		}
    	}
    };
    bool cmp(const stru &a,const stru &b)
    {
    	if (a.num == b.num)
    		return a.pos < b.pos;
    	return a.num > b.num;
    }
    int main()
    {
    	string tmp;
    	ac a;
    	int n;
    	while (cin >> n && n)
    	{
    		memset(trie, 0, sizeof(trie));
    		memset(fail, 0, sizeof(fail));
    		memset(cntword, 0, sizeof(cntword));
    		cnt = 0; strid = 0;
    		input.clear();
    		for (int i = 1; i <= n; ++i)
    		{
    			ans[i].num = 0;
    			ans[i].pos = i;
    			cin >> tmp;
    			input.push_back(tmp);
    			a.insert(tmp);
    		}
    		a.buildfail();
    		cin >> tmp;
    		a.query(tmp);
    		sort(ans + 1, ans + n + 1, cmp);
    		cout << ans[1].num << endl;
    		for (int i = 1; ans[i].num == ans[1].num; ++i)
    			cout << input[ans[i].pos - 1] << endl;
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    OTPUB知识课堂——VMware虚拟机应该如何优化
    春风十里,不如梭子鱼云安全解决方案全心为你!
    企业进行云存储,必须先搞清楚这5个问题
    OTPUB知识讲堂——如何在云计算中部署SQL
    Convertlab——营销的艺术,数字化的艺术
    腾讯云化解安全危机,开启网络安全智能时代
    11.2
    笔记
    this
    JS数据的基本类型
  • 原文地址:https://www.cnblogs.com/Aya-Uchida/p/11559843.html
Copyright © 2011-2022 走看看