zoukankan      html  css  js  c++  java
  • 【YBTOJ】【Luogu P3966】[TJOI2013]单词

    链接:

    洛谷

    题目大意:

    求每个单词分别在论文中出现了多少次。

    正文:

    对于整篇“论文”,也就是文本串,其实就是各个“单词”,即模式串,连接而成,而且有分隔符。

    那么接下来就与二次加强的 AC 自动机板子一模一样了:因为直接跳失配指针会被卡,所以建 fail 树,然后跑 DFS 或者拓扑。

    代码:

    const int N = 3e6 + 10, M = 160;
    
    inline ll Read()
    {
    	ll x = 0, f = 1;
    	char c = getchar();
    	while (c != '-' && (c < '0' || c > '9')) c = getchar();
    	if (c == '-') f = -f, c = getchar();
    	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
    	return x * f;
    }
    
    int n; 
    
    namespace AC
    {
    	int t[N][30], id[N], val[N], cnt[N], fail[N];
    	int tot;
    	void Insert(char *s, int I)
    	{
    		int p = 0, len = strlen(s);
    		for (int i = 0; i < len; i++)
    		{
    			int ch = s[i] - 'a';
    			if (!t[p][ch]) t[p][ch] = ++tot;
    			p = t[p][ch];
    		}
    		id[I] = p;
    	}
    	queue <int> q;
    	vector <int> e[N];
    	void Build()
    	{
    		while(!q.empty()) q.pop();
    		for (int i = 0; i < 26; i++)
    			if (t[0][i]) q.push(t[0][i]);
    		while (!q.empty())
    		{
    			int p = q.front(); q.pop();
    			for (int i = 0; i < 26; i++)
    				if (t[p][i])
    					fail[t[p][i]] = t[fail[p]][i], q.push(t[p][i]);
    				else
    					t[p][i] = t[fail[p]][i];
    		}
    		for (int i = 1; i <= tot; i++)
    			e[fail[i]].push_back(i);
    	}
    	void Query(char *s)
    	{
    		int p = 0, ans = 0, len = strlen(s);
    		for (int i = 0; i < len; i++)
    		{
    			p = t[p][s[i] - 'a'];
    			val[p]++;
    		}
    	}
    	void DFS(int u)
    	{
    		for (int i = 0, v; i < e[u].size(); i++)
    			DFS(v = e[u][i]), val[u] += val[v];
    	}
    }
    
    char s[N], t[N]; 
    
    int main()
    {
    	n = Read();
    	for (int i = 1; i <= n; i++)
    		scanf ("%s", s), AC::Insert(s, i), strcat(t, s), strcat(t, "@");
    	AC::Build();
    //	puts(t);
    	AC::Query(t);
    	AC::DFS(0);
    	for (int i = 1; i <= n; i++)
    		printf ("%d
    ", AC::val[AC::id[i]]);
    	return 0;
    }
    
  • 相关阅读:
    基于element-ui图片封装组件
    计算时间间隔具体每一天
    C语言学习笔记 —— 函数作为参数
    AtCoder Beginner Contest 049 题解
    AtCoder Beginner Contest 048 题解
    AtCoder Beginner Contest 047 题解
    AtCoder Beginner Contest 046 题解
    AtCoder Beginner Contest 045 题解
    AtCoder Beginner Contest 044 题解
    AtCoder Beginner Contest 043 题解
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/14836796.html
Copyright © 2011-2022 走看看