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;
    }
    
  • 相关阅读:
    如何在Windows下安装sass和compass
    HTTP 请求头中的 X-Forwarded-For
    HTTP 代理原理及实现
    node.js使用经验记录
    完美方案——iOS的WebView自适应内容高度
    购物车商品加减效果
    C++17新特性
    栈实现迷宫求解(c++版)
    二叉树遍历及实现
    经典乱码“烫烫烫”和“屯屯屯”
  • 原文地址:https://www.cnblogs.com/hyxss/p/13883382.html
Copyright © 2011-2022 走看看