zoukankan      html  css  js  c++  java
  • [POI2000]病毒

    如果存在一个环,且环上没有任何危险标记(即病毒代码段末尾一位的结点专门作的编号),此时 AC自动机 能一直在环上匹配,并且永远也不会得到为模式串的一个子串, 这个找环可以通过 dfs 来实现
    在构造失配指针时,一个很明显的优化是:如果一个结点拥有了失配指针,它指向的结点如果有危险标记,自己必然也危险,因为它到根结点形成的串是自己到根节点的后缀。

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 2e5 + 5;
    
    int n, cnt;
    int vis[N], ins[N];
    string a[2005];
    struct str {
    	int end;
    	int fail;
    	int ch[2];
    } AC[25000];
    
    void build(string s) {
    	int now = 0;
    	for(int i = 0; i < s.size(); i++) {
    		if(!AC[now].ch[s[i] - '0']) 
    			AC[now].ch[s[i] - '0'] = ++cnt;
    		now = AC[now].ch[s[i] - '0'];
    	}
    	AC[now].end = 1;
    }
    void Get_fail() {
    	queue<int> q;
    	int now = 1;
    	for(int i = 0; i <= 1; i++) 
    		if(AC[0].ch[i])
    			AC[AC[0].ch[i]].fail = 0, q.push(AC[0].ch[i]);
    	while(!q.empty()) {
    		int u = q.front(); q.pop();
    		for(int i = 0; i <= 1; i++) {
    			if(AC[u].ch[i]) {
    				AC[AC[u].ch[i]].fail = AC[AC[u].fail].ch[i];
    				AC[AC[u].vis[i]].end |= AC[AC[AC[u].vis[i]].fail].end;
    				q.push(AC[u].ch[i]);
    			}
    			else AC[u].ch[i] = AC[AC[u].fail].ch[i];
    		}
    	}
    }
    void dfs(int x) {
    	if(ins[x]) {cout << "TAK
    "; exit(0);}
    	if(AC[x].end || vis[x])  return ;
    	vis[x] = ins[x] = 1;
    	dfs(AC[x].ch[0]);//注意这里不要判断(  if(AC[x].ch[0]) )因为一个安全的代码可以不在trie树上~~趴~~
    	dfs(AC[x].ch[1]);
    	ins[x] = 0;
    }
    int main() {
    	cin >> n;
    	for(int i = 1; i <= n; i++) {
    		cin >> a[i];
    		build(a[i]);
    	}
    	Get_fail(); dfs(0);
    	cout << "NIE
    ";
    	return 0;
    }
    
  • 相关阅读:
    poj 3122 (二分查找)
    poj 1064 (二分+控制精度) && hdu 1551
    hdu 2199 (二分)
    hdu 2141 (二分)
    poj 2954 Triangle(Pick定理)
    poj 1265 Area (Pick定理+求面积)
    hdu 4946 Just a Joke(数学+物理)
    zoj 1199 几何公式推导
    MMORGP大型游戏设计与开发(客户端架构 part13 of vegine)
    MMORPG大型游戏设计与开发(客户端架构 part12 of vegine)
  • 原文地址:https://www.cnblogs.com/hyxss/p/13883382.html
Copyright © 2011-2022 走看看