(2896)HDU

#include<iostream>
#include<cstdio>
#include<string.h>
#include<string>
#include<set>
#include<algorithm>
#include<cmath>
#include<queue>

#define ll __int64
#define MAX 1000009

const int maxnode = 210*500;
const int sigma_size = 128;

using namespace std;

struct Trie
{
    int ch[maxnode][sigma_size];
    int val[maxnode];
    int next[maxnode];
    int sz,root;
    int newnode()//建立新的结点,跟以前写的不一样,但是我觉得这种写法更好一些
    {
        for(int i = 0; i<128; i++)
            ch[sz][i] = -1;
        val[sz++] = -1;
        return sz - 1;
    }
    void init()//初始化
    {
        sz = 0;
        root = newnode();
    }
    void Insert(char* s,int id)//插入
    {
        int n = strlen(s);
        int u = root;
        for(int i = 0; i<n; i++)
        {
            if(ch[u][s[i]]==-1)
                ch[u][s[i]] = newnode();
            u = ch[u][s[i]];//向下走
        }
        val[u] = id;//在节点进行标记
    }
    void build()//建立next数组
    {
        queue<int>Q;
        next[root] = root;
        for(int i = 0; i<128; i++)//第1次循环时处理与root相连的字符
        {
            if(ch[root][i]==-1)//没有存在的点都指向root
            {
                ch[root][i] = root;
            }
            else//如果存在
            {
                next[ch[root][i]] = root;;//第一个字符不需要匹配,所以都指向root
                Q.push(ch[root][i]);//把与root连接的点都入队
            }
        }
        while(!Q.empty())
        {
            int now = Q.front();//取队首
            Q.pop();
            for(int i = 0; i<128; i++)
            {
                if(ch[now][i]==-1)//当ch[now][i]不存在时,让 ch[now][i] = ch[next[now]][i],构造Tire图
                {
                    ch[now][i] = ch[next[now]][i];//
                }
                else
                {
                    next[ch[now][i]] = ch[next[now]][i];
                    Q.push(ch[now][i]);
                }
            }
        }
    }
    int ss[10010];
    int query(char* s,int id)//扫描查询
    {
        int len = strlen(s);
        int now = root;
        int res = 0;
        memset(ss,0,sizeof(ss));
        for(int i = 0; i<len; i++)
        {
            now = ch[now][s[i]];
            int temp = now;//在建立fail指针时有寻找与字符匹配的结点的作用
            while(temp!= root)//计算后缀串
            {
                if(val[temp]!=-1)
                {
                    ss[val[temp]] = 1;
                    res = 1;
                    //val[temp] = 0;
                }
                temp = next[temp];
            }
        }
        if(res==0)
            return 0;
        printf("web %d:",id);
        for(int i = 1; i<510; i++)
        {
            if(ss[i])
                printf(" %d",i);
        }
        printf("\n");
        return 1;
    }
};

char str[MAX];
Trie Ac;

int main()
{
    int T;
    int n,m;
    int sum;
    //scanf("%d",&T);
    while(scanf("%d",&n)!=EOF)
    {
        Ac.init();
        for(int i = 1; i<=n; i++)
        {
            scanf("%s",str);
            Ac.Insert(str,i);
        }
        Ac.build();
        scanf("%d",&m);
        sum = 0;
        for(int i = 1; i<=m; i++)
        {
            scanf("%s",str);
            if(Ac.query(str,i))
            {
                sum++;
            }
        }
        printf("total: %d\n",sum);
    }
    return 0;

}

调了一天的代码,错误在于应该是128,我一直写26.。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值