zoukankan      html  css  js  c++  java
  • 【YBTOJ】【Luogu P3121】[USACO15FEB]Censoring G

    链接:

    洛谷

    题目大意:

    【Luogu P4824】[USACO15FEB]Censoring S的强化版。

    (S) 中从头开始寻找屏蔽词,一旦找到一个屏蔽词,就删除它,然后又从头开始寻找(而不是接着往下找)。

    (n) 个屏蔽词。

    正文:

    多模式串匹配,考虑用 AC 自动机。详见弱化版。

    但是按朴素算法直接跳失配指针的话,复杂度就假了。所以还是建 fail 树然后跑 DFS。然后因为 trie 树的存储方式本来就很链表,所以不需用多余的维护。

    代码:

    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; 
    char s[N], t[N], ans[N]; 
    
    namespace AC
    {
    	int t[N][30], val[N], cnt[N], fail[N], Len[N], stk[N], a[N];
    	int tot;
    	void Insert(char *s, int I)
    	{
    		int p = 0, len = strlen(s);
    		Len[I] = len;
    		for (int i = 0; i < len; i++)
    		{
    			int ch = s[i] - 'a';
    			if (!t[p][ch]) t[p][ch] = ++tot;
    			p = t[p][ch];
    		}
    		val[p] = I;
    	}
    	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 DFS(int u)
    	{
    		for (int i = 0; i < e[u].size(); i++)
    		{
    			int v = e[u][i];
    			if (val[u]) val[v] = val[u];
    			DFS(v);
    		}
    	}
    	void Query(char *s)
    	{
    		int p = 0, len = strlen(s), top = 0, m = 0;
    		for (int i = 0; i < len; i++)
    		{
    			p = t[p][s[i] - 'a'];
    			if (val[p]) a[i] = Len[val[p]], top -= Len[val[p]] - 1, p = stk[top];
    			else stk[++top] = p;
    		}
    		for (int i = len - 1, Dlt = 0; ~i; i--)
    		{
    			Dlt += a[i];
    			if (Dlt) Dlt--;
    			else ans[m++] = s[i];
    		}
    		for (int i = m - 1; ~i; i--) printf("%c", ans[i]);
    	}
    }
    
    
    int main()
    {
    	scanf("%s", t);
    	n = Read();
    	for (int i = 1; i <= n; i++)
    		scanf ("%s", s), AC::Insert(s, i);
    	AC::Build();
    	AC::DFS(0);
    	AC::Query(t);
    	return 0;
    }
    
  • 相关阅读:
    Spring中的一些常用接口
    ApplicationContextAware的作用
    用spring的 InitializingBean 的 afterPropertiesSet 来初始化
    虚拟机扩容(/dev/mapper/centos-root 空间不足)
    AJAX
    Git
    jQuery
    JS
    JS
    jQuery
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/14842113.html
Copyright © 2011-2022 走看看