hdu2896(病毒侵袭)

来源:互联网 发布:ps软件怎么用 编辑:程序博客网 时间:2024/06/05 15:21

#include<iostream>#include<cstring>#include<queue>#include<map>#include<algorithm>#include<cstdio>using namespace std;const int maxn = 128;char ss[10000+maxn];int vis[501];struct Node{    Node *next[maxn];    Node *pre;//前缀指针    int last,id;    Node ()//初始化数据    {        memset(next, 0, sizeof (next));        pre =NULL, last = 0,id=0;    }};Node *root;void Init (){    root = new Node;}void Insert (char *s,int id){    if (!s[0]) return ;    Node *p = root;    for (int i = 0; s[i]; i++)    {        int k=s[i]-' ';        if (!p -> next[k])            p -> next[k] = new Node;        p = p -> next[k];    }    p -> last++;//记录该节点单词总共插入的次数    p->id=id;}void Build ()//建立前缀指针{    queue <Node*> qu;    for (int i = 0; i < maxn; i++)        if (root -> next[i])        {            root -> next[i] -> pre = root;            qu.push (root -> next[i]);//层次遍历建立前缀指针        }    while (!qu.empty ())    {        Node *temp = qu.front (); qu.pop ();        for (int i = 0; i < maxn; i++)        {            Node *pp = temp -> next[i];            if (pp)            {                Node *par = temp -> pre;                do                {                    if (par -> next[i])                    {                        pp -> pre = par -> next[i];                        break;                    }                    else                        par = par -> pre;                } while (par);                if (!par)                    pp -> pre = root;                qu.push (pp);//继续层次遍历建立前缀指针            }        }    }}int Query(char *s){    if (!s[0]) return 0;    Node *p = root;    int cnt = 0;    for (int i = 0; s[i]; i++)    {        int k=s[i]-' ';        while (p != root && !p -> next[k])            p = p -> pre;        p = p -> next[k];//现在所在位置为父节点,需要向下移动一个位置        if (!p)            p = root;//若匹配失败,移到根节点重新匹配        Node *pp = p;        while (pp != root && pp -> last != -1)//若匹配成功,last>0,代表该节点的单词数量,        {                                     //否则表示该节点没有单词            if(pp->last>0)            {                cnt+=pp->last;//统计该单词出现的次数                vis[pp->id]=1;            }           // pp -> last = -1;//可以重复查找,故不能置为-1            pp = pp -> pre;//继续判断整条链上的情况        }    }    return cnt;}void DelTree (Node *s){    if (!s) return ;    for (int i = 0; i < maxn; i++)    {        if (s -> next[i])            DelTree (s -> next[i]);    }    delete s;}int main(){    int n;    scanf ("%d",&n);    Init ();    for (int i = 1; i <= n; i++)    {        scanf ("%s", ss);        Insert (ss,i);    }    getchar();    Build ();    int m;    scanf("%d",&m);    int total=0;    for(int i=1;i<=m;i++)    {        memset(vis,0,sizeof(vis));        scanf ("%s", ss);        int tmp=Query(ss);        getchar();        if(tmp)        {            printf("web %d:",i);            for(int j=1;j<=n;j++)            {                if(vis[j]) cout<<' '<<j;            }            cout<<endl;            total++;        }    }    DelTree (root);    printf("total: %d\n",total);    return 0;}

0 0
原创粉丝点击