HDU2896AC自动机模板

来源:互联网 发布:淘宝网床上用品 编辑:程序博客网 时间:2024/05/18 12:37

病毒侵袭

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 10281    Accepted Submission(s): 2670


Problem Description
当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻。。。。在这样的时刻,人们却异常兴奋——我们能在有生之年看到500年一遇的世界奇观,那是多么幸福的事儿啊~~
但网路上总有那么些网站,开始借着民众的好奇心,打着介绍日食的旗号,大肆传播病毒。小t不幸成为受害者之一。小t如此生气,他决定要把世界上所有带病毒的网站都找出来。当然,谁都知道这是不可能的。小t却执意要完成这不能的任务,他说:“子子孙孙无穷匮也!”(愚公后继有人了)。
万事开头难,小t收集了好多病毒的特征码,又收集了一批诡异网站的源码,他想知道这些网站中哪些是有病毒的,又是带了怎样的病毒呢?顺便还想知道他到底收集了多少带病毒的网站。这时候他却不知道何从下手了。所以想请大家帮帮忙。小t又是个急性子哦,所以解决问题越快越好哦~~
 

Input
第一行,一个整数N(1<=N<=500),表示病毒特征码的个数。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在20—200之间。
每个病毒都有一个编号,依此为1—N。
不同编号的病毒特征码不会相同。
在这之后一行,有一个整数M(1<=M<=1000),表示网站数。
接下来M行,每行表示一个网站源码,源码字符串长度在7000—10000之间。
每个网站都有一个编号,依此为1—M。
以上字符串中字符都是ASCII码可见字符(不包括回车)。
 

Output
依次按如下格式输出按网站编号从小到大输出,带病毒的网站编号和包含病毒编号,每行一个含毒网站信息。
web 网站编号: 病毒编号 病毒编号 …
冒号后有一个空格,病毒编号按从小到大排列,两个病毒编号之间用一个空格隔开,如果一个网站包含病毒,病毒数不会超过3个。
最后一行输出统计信息,如下格式
total: 带病毒网站数
冒号后有一个空格。
 

Sample Input
3aaabbbccc2aaabbbcccbbaacc
 

Sample Output
web 1: 1 2 3total: 1
 

Source
2009 Multi-University Training Contest 10 - Host by NIT 

关于
shr
h
下面的版建树是这样的
黑线为字典树转移,红线为失败指针,蓝线为优化指针


整合版,加入节点转移优化,当一个节点为空时直接转移至fail节点
#define DeBUG#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <algorithm>#include <vector>#include <stack>#include <queue>#include <string>#include <set>#include <sstream>#include <map>#include <list>#include <bitset>using namespace std ;#define zero {0}#define INF 0x3f3f3f3f#define EPS 1e-6typedef long long LL;const double PI = acos(-1.0);//#pragma comment(linker, "/STACK:102400000,102400000")inline int sgn(double x){    return fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1);}#define N 100005#define cha 128#define TRUE true#define FALSE false#define Type intbool used[510];struct Trie{    int next[N][cha];    int fail[N];    Type end[N];//用于存放目标节点数据    int Root, L;    int newnode()    {        for (int i = 0; i < cha; i++)            next[L][i] = -1;        end[L] = -1;//数据域        L++;        return L - 1;    }    void init()    {        L = 0;        Root = newnode();    }    void insert(char s[], int id)    {        int len = strlen(s);        int now = Root;        int ti;        for (int i = 0; i < len; i++)        {            ti = s[i];//ti下标            if (next[now][ti] == -1)                next[now][ti] = newnode();            now = next[now][ti];        }        end[now] = id;//数据域    }    void build()    {        queue<int>Q;        fail[Root] = Root;        for (int i = 0; i < cha; i++)        {            if (next[Root][i] == -1)                next[Root][i] = Root;            else            {                fail[next[Root][i]] = Root;                Q.push(next[Root][i]);            }        }        while (!Q.empty())        {            int now = Q.front();            Q.pop();            for (int i = 0; i < cha; i++)            {                if (next[now][i] == -1)                    next[now][i] = next[fail[now]][i];                else                {                    fail[next[now][i]] = next[fail[now]][i];                    Q.push(next[now][i]);                }            }        }    }    bool query(char buf[], int n)    {        int len = strlen(buf);        int now = Root;        int ti;        bool flag = false;        for (int i = 0; i < len; i++)        {            ti = buf[i];//ti下标            now = next[now][ti];            int temp = now;            while (temp != Root)            {                if (end[temp] != -1) //数据域                {                    flag = true;                    used[end[temp]] = TRUE;//数据域                }                temp = fail[temp];            }        }        return flag;    }    void debug()    {        for (int i = 0; i < L; i++)        {            printf("id = %3d, fail = %3d, end = %3d, \n", i, fail[i], end[i]);            // printf("word= [");            // for(int j=0;j<cha;j++)            //     printf("%2c", j+'a');            // printf("]\n");            printf("chi = [");            for (int j = 0; j < cha; j++)                printf("%2d", next[i][j]);            printf("]\n\n");        }    }};char buf[10010];Trie ac;int main(){#ifdef DeBUGs    freopen("C:\\Users\\Sky\\Desktop\\1.in", "r", stdin);#endif    int n, m;    while (scanf("%d", &n) + 1)    {        ac.init();        for (int i = 1; i <= n; i++)        {            scanf("%s", buf);            ac.insert(buf, i);        }        ac.build();        // ac.debug();        int ans = 0;        scanf("%d", &m);        for (int i = 1; i <= m; i++)        {            memset(used, 0, sizeof(used));            scanf("%s", buf);            if (ac.query(buf, n))            {                ans++;                printf("web %d:", i);                for (int j = 1; j <= n; j++)                {                    if (used[j])                    {                        printf(" %d", j);                    }                }                printf("\n");            }        }        printf("total: %d\n", ans);    }    return 0;}




非整合版,常规建树
关于
shr
h
下面的版建树是这样的
#define DeBUG#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <algorithm>#include <vector>#include <stack>#include <queue>#include <string>#include <set>#include <sstream>#include <map>#include <list>#include <bitset>using namespace std ;#define zero {0}#define INF 0x3f3f3f3f#define EPS 1e-6typedef long long LL;const double PI = acos(-1.0);//#pragma comment(linker, "/STACK:102400000,102400000")inline int sgn(double x){    return fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1);}#define N 100005#define Root 0#define cha 129struct node{    int data;    int count;    int fail;    int next[cha];};node tree[N];void init(node &a, int data){    a.data = data;    a.count = 0;    a.fail = Root;    for (int i = 0; i < cha; i++)        a.next[i] = -1;}int ID = 1;void Insert(char s[], int id){    int p = Root;    for (int i = 0; s[i]; i++)    {        int data = s[i];        if (tree[p].next[data] == -1)        {            init(tree[ID], data);            tree[p].next[data] = ID;            ID++;        }        p = tree[p].next[data];    }    tree[p].count = id;}void AC_automation(){    queue<node>Q;    Q.push(tree[Root]);    while (!Q.empty())    {        node now = Q.front();        Q.pop();        for (int j = 0; j < cha; j++)        {            if (now.next[j] != -1)            {                if (now.data == -1)                    tree[now.next[j]].fail = Root;                else                {                    int t = now.fail;                    while (t != Root && tree[t].next[j] == -1)                    {                        t = tree[t].fail;                    }                    tree[now.next[j]].fail = max(tree[t].next[j], Root);                }                Q.push(tree[now.next[j]]);            }        }    }}bool is[1005];int get_ans(char s[]){    int p = Root, ans = 0;    for (int i = 0; s[i]; i++)    {        int t = s[i];        while (tree[p].next[t] == -1 && p)        {            p = tree[p].fail;        }        p = tree[p].next[t];        if (p == -1)        {            p = Root;            continue;        }        int j = p;        while (tree[j].count)        {            ans++;            is[tree[j].count] = 1;            j = tree[j].fail;        }        // 如果走到头以后当前字母不是关键字终点然而其fail指针指向字母是关键字终点的话,应当加入此关键值        if (tree[ tree[j].fail ].count)        {            ans++;            is[tree[ tree[j].fail ].count] = 1;        }    }    return ans;}char word[10005];char code[10005];int main(){#ifdef DeBUGs    freopen("C:\\Users\\Sky\\Desktop\\1.in", "r", stdin);#endif    int n;    while (scanf("%d", &n) + 1)    {        int m;        init(tree[Root], -1);        for (int i = 1; i <= n; i++)        {            scanf("%s", word);            Insert(word, i);        }        AC_automation();        scanf("%d", &m);        int total = 0;        for (int j = 1; j <= m; j++)        {            memset(is, 0, sizeof(is));            scanf("%s", code);            int num = get_ans(code);            if (num != 0)            {                total++;                printf("web %d:", j);                for (int i = 1; i <= n; i++)                {                    if (is[i])                    {                        printf(" %d", i);                    }                }                printf("\n");            }        }        printf("total: %d\n", total);    }    return 0;}



0 0
原创粉丝点击