HDU 2896 (AC自动机模板题)

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=2896

题目大意:多个模式串。多个匹配串。其中串的字符范围是(0~127)。问匹配串中含有哪几个模式串。

解题思路

AC自动机模板题。注意一下字符范围。

cnt记录这个模式串的个数改为这个模式串的index。

find的时候,把找到的index压入vector里面即可。

注意有多个匹配串,每次find之后会把last->cnt修改,原因是防止一个模式串出现了多次被压入vector,所以先备份一下,再还原回来。

 

#include "cstdio"

#include "cstring"

#include "string"

#include "iostream"

#include "queue"

#include "vector"

#include "algorithm"

using namespace std;

#define maxn 130

struct Trie

{

    Trie *next[maxn],*fail;

    int cnt;

}*root;

struct status

{

    Trie *last;

    int cnt;

    status(Trie *last,int cnt):last(last),cnt(cnt) {}

};

Trie *newnode()

{

    Trie *ret=new Trie;

    memset(ret->next,0,sizeof(ret->next));

    ret->fail=0;

    ret->cnt=0;

    return ret;

}

void init() {root=newnode();}

void Insert(string str,int index)

{

    Trie *pos=root;

    for(int i=0;i<str.size();i++)

    {

        int c=str[i];

        if(!pos->next[c]) pos->next[c]=newnode();

        pos=pos->next[c];

    }

    pos->cnt=index;

}

void getfail()

{

    queue<Trie *> Q;

    for(int c=0;c<maxn;c++)

    {

        if(root->next[c])

        {

            root->next[c]->fail=root;

            Q.push(root->next[c]);

        }

        else root->next[c]=root;

    }

    while(!Q.empty())

    {

        Trie *x=Q.front();Q.pop();

        for(int c=0;c<maxn;c++)

        {

            if(x->next[c])

            {

                x->next[c]->fail=x->fail->next[c];

                Q.push(x->next[c]);

            }

            else x->next[c]=x->fail->next[c];

        }

    }

}

vector<int> find(string str)

{

    Trie *pos=root,*last;

    queue<status> Q;

    vector<int> ans;

    for(int i=0;i<str.size();i++)

    {

        int c=str[i];last;

        if(pos->next[c])

        {

            pos=pos->next[c];

            last=pos;

            while(last->cnt)

            {

                Q.push(status(last,last->cnt));

                ans.push_back(last->cnt);

                last->cnt=0; //修改last->cnt

                last=last->fail;

            }

        }

    }

    while(!Q.empty()) //恢复last->cnt

    {

        status x=Q.front();Q.pop();

        x.last->cnt=x.cnt;

    }

    return ans;

}

int main()

{

    //freopen("in.txt","r",stdin);

    ios::sync_with_stdio(false);

    int n,m;

    string tt;

    while(cin>>n)

    {

        init();

        for(int i=1;i<=n;i++)

        {

            cin>>tt;

            Insert(tt,i);

        }

        getfail();

        cin>>m;

        int cnt=0;

        for(int i=1;i<=m;i++)

        {

            cin>>tt;

            vector<int> ans=find(tt);

            sort(ans.begin(),ans.end());

            if(!ans.size()) continue;

            cnt++;

            printf("web %d:",i);

            for(int j=0;j<ans.size();j++) printf(" %d",ans[j]);

            printf("\n");

        }

        printf("total: %d\n",cnt);

    }

}

 

 

你可能感兴趣的:(AC自动机)