现在的位置: 首页 > 综合 > 正文

[HDU 3065]病毒侵袭持续中[AC自动机][模板题]

2019年04月05日 ⁄ 综合 ⁄ 共 1953字 ⁄ 字号 评论关闭

很久没有自己敲一个题了,这道又WA得我内!牛!满!面!啊......不过还是得这样才印象深刻.

记得检查输入是否正确.不要焦躁.

AC了之后感觉忽然有了力量~

题意:给出许多模式串,一个源码,求源码中都有哪些模式串出现了,分别出现几次.

思路:AC_Automation中,注意模式串之间有重叠的情况,就是无论是否匹配到了当前串的末尾,都要借助一个tmp指针往回找一遍,看看别的链上是否有可以匹配的.一直找到根为止.

对于输出要求,首先trie树的尾节点标记id为输入序号,从0开始.同时准备一个结构体数组,按照id顺序存病毒名和出现次数.

#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
using namespace std;
int n;
inline int GetId(char c)
{
    return c - 'A';
}
typedef struct virus
{
    string name;
    int freq;
}virus;
class node{
public:
    node *chd[26];
    node *fail;
    int id;

    node(){
        memset(chd,0,sizeof(chd));
        fail = NULL;
        id = -1;
    }
};

class AC_Automation
{
public:
    node *root;
    queue <node*> q;
    virus v[1005];

    AC_Automation(){
        root = new node;
        while(!q.empty())   q.pop();
        for(int i=0;i<n;i++)
            v[i].freq = 0;
    }
    void insert(string s,int th)
    {
        node *cur = root;
        int len = s.length();
        for(int i=0;i<len;i++)
        {
            int index = GetId(s[i]);
            if(!cur->chd[index])      cur->chd[index] = new node;
            cur = cur->chd[index];
        }
        cur->id = th;
        v[th].name = s;
    }
    void BuildAC()
    {
        node *cur,*tmp;
        q.push(root);
        while(!q.empty())
        {
            cur = q.front();
            q.pop();
            for(int i=0;i<26;i++)
            {
                if(cur->chd[i])
                {
                    if(cur == root)     cur->chd[i]->fail = root;
                    else
                    {
                        tmp = cur->fail;
                        while(tmp->fail && !tmp->chd[i])   tmp = tmp->fail;///*
                        if(tmp->chd[i])     cur->chd[i]->fail = tmp->chd[i];
                        else    cur->chd[i]->fail = root;
                    }
                    q.push(cur->chd[i]);
                }
            }
        }
    }
    void query(string s)
    {
        node *cur = root,*tmp;///shers
        int len = s.length();
        for(int i=0;i<len;i++)
        {
            int index = GetId(s[i]);
            if(index<0 ||index>=26)
            {
                cur = root;//puts("here");
                continue;
            }
            if(cur->chd[index]) cur = cur->chd[index];
            else
            {
                while(cur && !cur->chd[index])     cur =  cur->fail;///*
                if(!cur)    cur = root;
                if(cur->chd[index])     cur = cur->chd[index];
            }
            tmp = cur;
            while(tmp->fail)///为了处理相互重叠或相互包含的情况
            {
                if(tmp->id > -1)
                    v[tmp->id].freq++;
                tmp = tmp->fail;

            }
        }
    }
    void PrintRes()
    {
        for(int i=0;i<n;i++)
        {
            if(v[i].freq)   cout<<v[i].name<<": "<<v[i].freq<<endl;
        }
    }
};
char pat[52],tar[2000005];

int main()
{
    while(scanf("%d",&n)==1)
    {
        AC_Automation AC;
        getchar();
        for(int i=0;i<n;i++)
        {
            gets(pat);
          //  cout<<"pat "<<pat<<endl;
            AC.insert(pat,i);
        }
        AC.BuildAC();
        gets(tar);
       // cout<<"tar "<<tar<<endl;
        AC.query(tar);

        AC.PrintRes();
    }
}

抱歉!评论已关闭.