病毒侵袭 HDU - 2896 ac自动机(记录方案)

#include<cstdio>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int tr[N][130],n,m,idx,ne[N],ed[N],cnt,cas=1;
int vis[N];
char str[N];
void insert(char str[],int id)
{
    int len=strlen(str),now=0;
    for(int i=0;i<len;i++)
    {
        int x=str[i];
        if(!tr[now][x])
            tr[now][x]=++idx;
        now=tr[now][x];
    }
    //在病毒尾部加编号 
    ed[now]=id;
}
void build()
{
    queue<int>q;
    while(q.size())
        q.pop();
    for(int i=0;i<=128;i++)
        if(tr[0][i])
            q.push(tr[0][i]);
    while(q.size())
    {
        int now=q.front();
        q.pop();
        for(int i=0;i<=128;i++)
        {
            if(!tr[now][i])
            {
                tr[now][i]=tr[ne[now]][i];
                continue;
            }
            ne[tr[now][i]]=tr[ne[now]][i];
            q.push(tr[now][i]);
        }
    }
}
void query(char str[])
{
    int use[510]={0};
    int len=strlen(str);
    int now=0,flag=0;
    for(int i=0;i<len;i++)
    {
        vis[now]=1;
        int x=str[i];
        int y=tr[now][x];
        while(y&&!vis[y])//只查找一次,所以要标记y
        {
            vis[y]=1;
            if(ed[y])
            {
                use[ed[y]]=1;
                flag=1;
            }
            y=ne[y];
        }
        now=tr[now][x];
    }
    if(flag)
    {
        printf("web %d:",cas);
        //输出用过的编号 
        for(int i=0;i<510;i++)
            if(use[i]==1)
                printf(" %d",i);
        cnt++;
        printf("\n");
    }
}
int main() {
    
    idx = 0;
    scanf("%d", &n);
    for (int i = 1; i <= n; i ++ ) {
        scanf("%s", &str);
        insert(str,i);
    }
    cin>>m;
    build();
    for(int i=1;i<=m;i++)
    {
        scanf("%s",&str);
        memset(vis,0,sizeof(vis));//查询下一个文本,需要重置vis标记
        query(str);
        cas++;
    }
    printf("total: %d\n",cnt);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/QingyuYYYYY/p/12523317.html
今日推荐