ZOJ3228 Trie树

来源:互联网 发布:入驻淘宝外卖收费标准 编辑:程序博客网 时间:2024/06/06 07:45

       卡内存呀有木有,本来这题往AC自动机上想是很自然的,但是这题内存给的非常紧,开不下指针形式的节点,最后只能用数组形式的Trie树才能卡过,我们把长串所有长度为6的子串插入Trie树,然后对于第一类查找应该是很容易的,对于第二类查找我们记录上次到达这个节点的时候下标是多少,等再次插入到这个点的时候我们只要看当前下标和上次的下标之差是不是大于这个字符串的长度,大于就更新第二类查询的个数,同时更新上次到达这个节点的下标值。

    

#include <iostream>#include <cstring>#include <cstdio>#define N 100005#define Max 26typedef long long LL;using namespace std;struct node{    int c[2];    int lc;    int next[Max];}tree[6*N];int cnt,tp,root;char s[N],word[10];int newnode(){    for(int i=0; i<Max; i++) tree[cnt].next[i]=-1;    tree[cnt].c[0] = tree[cnt].c[1] = 0;    tree[cnt].lc = -1;    return cnt++;}void insert(char *str,int x){    int i=x;    int t = root;    while(i<x+6&&str[i])    {        int id = str[i]-'a';        if(tree[t].next[id]==-1)            tree[t].next[id]=newnode();        t=tree[t].next[id];        tree[t].c[0]++;        if(tree[t].lc<x)        {            tree[t].c[1]++;            tree[t].lc = i;        }        i++;    }}int query(){    int tmp = root,i = 0;    while(word[i])    {        int x = word[i]-'a';        if(tree[tmp].next[x] == -1)return 0;        tmp = tree[tmp].next[x];        i++;    }    return tree[tmp].c[tp];}int main(){    int n,i,j,cas = 1;    while(scanf("%s",s)!=EOF)    {        cnt = 0;        root = newnode();        int l = strlen(s);        for(i = 0;i<l;i++)insert(s,i);        scanf("%d",&n);        printf("Case %d\n",cas++);        for(i = 1;i<=n;i++)        {            scanf("%d%s",&tp,word);            printf("%d\n",query());        }        printf("\n");    }    return 0;}

原创粉丝点击