zoj 3228 Searching the String(trie)

题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3441

先把源码插入tree中,然后统计能够重叠的情况和不能重叠的情况,并把信息存储起来,最后依据给出的0 1输出统计的结果。考虑到内存,用数组不用指针。这种用数组写出的trie树可以过。

#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int nn=26,maxn=1e5+10;
int N,top,root,tp;
char str[maxn],keyword[10];
struct node{
    int next[nn],c[2];
    int loc;
}tree[6*maxn];
int newnode(){
    for(int i=0;i<nn;i++)tree[top].next[i]=-1;
    tree[top].c[0]=tree[top].c[1]=0;
    tree[top].loc=-1;
    return top++;
}
void insert_t(int dex){
    int i=dex,p=root;
    while(i<dex+6&&str[i]){
        int id=str[i]-97;
        if(tree[p].next[id]==-1)tree[p].next[id]=newnode();
        p=tree[p].next[id];
        tree[p].c[0]++;
        if(tree[p].loc<dex){
            tree[p].c[1]++;
            tree[p].loc=i;
        }
        i++;
    }
}
int query(){
    int temp=root,i=0;
    while(keyword[i]){
        int t=keyword[i]-97;
        if(tree[temp].next[t]==-1)return 0;
        temp=tree[temp].next[t];
        i++;
    }
    return tree[temp].c[tp];
}
int main(){
    //freopen("cin.txt","r",stdin);
    int cas=1;
    while(~scanf("%s",str)){
        top=0;
        root=newnode();
        int length=strlen(str);
        for(int i=0;i<length;i++){  //here 
            insert_t(i);
        }
        scanf("%d",&N);
        printf("Case %d\n",cas++);
        for(int i=0;i<N;i++){
            scanf("%d%s",&tp,keyword);
            printf("%d\n",query());
        }
        puts("");
    }
    return 0;
}
代码中的here: 用length存储strlen的结果,不然在循环中反复计算就超时了。(自己当时就犯这种错误)
本来也想用AC解决的,结果中间有一个错误不理解也改不了。。。贴上来,说不定哪天自己就看出来了:
#include <iostream>
#include<cstdio>
#include<cstring>
#include <queue>
using namespace std;
const int nn=26,maxn=1e5+10;
char str[maxn],word[15];
struct node{
    int pos,len,id[2];
    node *next[27],*fail;
    node(){
        pos=-1;
        id[0]=id[1]=len=0;
        fail=NULL;
        memset(next,0,sizeof(next));
    }
};
node *root,*que[maxn*6];
int *question[maxn];   //因为要保存值,所以要设成指针数组. 指针只读不写!
void insert(char *s,int tag,int dex){
    node *p=root;
    int length=strlen(s);
    for(int i=0;i<length;i++){
         if(p->next[s[i]-'a']==0)
             p->next[s[i]-'a']=new node();
         p=p->next[s[i]-'a'];
    }
    p->len=length;
    question[dex]=&(p->id[tag]);
}
void build_fail(){
    int head=0,tail=0;
    que[tail++]=root;
    while(head<tail){
         node *p=que[head++],*temp=NULL;
         for(int i=0;i<nn;i++){
             if(p->next[i]){
                 node *f=p->fail;
                 while(f){
                      if(f->next[i]){
                          p->next[i]->fail=f->next[i];  //对应图
                          break;
                      }
                      f=f->fail;
                 }
                 if(f==root)f->next[i]->fail=root;
                 que[tail++]=p->next[i];
             }
         }
    }
}
void find(char *s){ //fail指针,KMP都是紧密相连的
    int length=strlen(s);
    node *p=root;
    for(int i=0;i<length;i++){
        int k=s[i]-'a';
        while(p->next[k]==NULL&&p!=root)p=p->fail;
        /*p=p->next[k];  //this sentence is wrong, it make program stop *******************
        if(!p)p=root;    //调整目标串的对应起点
        node *tmp=p;
        while(tmp!=root){  //回到根节点说明就已经把能找的都找完了,如果一开始tmp就等于root,那么起点就是长串的第一个字符,顺推~
             if(tmp->len>0){
                tmp->id[0]++;
                if(tmp->pos==-1 || i-tmp->pos>=tmp->len){  //i-tmp->pos>=tmp->len  not >
                      tmp->id[1]++;
                      tmp->pos=i;  //更新
                }
             }
             tmp=tmp->fail;
        }*/
    }
}
void del(node *p){
     if(p==NULL)return ;
     for(int i=0;i<nn;i++)del(p->next[i]);
     delete p;
}
int main()
{
    freopen("cin.txt","r",stdin);
    int ca=1;
    while(cin>>str){
         root=new node();
         int n,tag;
         scanf("%d",&n);
         for(int i=0;i<n;i++){
             scanf("%d%s",&tag,word);
             insert(word,tag,i);
         }
         build_fail();
         node *p=root;
         cout<<str<<endl;
         find(str);
         printf("Case %d\n",ca++);
         cout<<*question[0]<<endl;
         for(int i=0;i<n;i++){
             printf("%d\n",*question[i]);
         }
         puts("");
         del(root);
    }
    return 0;
}

错误:0x3C0000005

----------------------------------------------------------------------------------------------------------------------------------------

2016. 03 .31

插入的思想都不一样,当然出现各种错误了。应该是把长串上的各个连续子串都放进trie树。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值