基本功能

1.字典树插入字符串。
2.字典树中查询字符串是否出现。
3.输出字典树中已存字符串以及出现次数。
4.在字典树中删除字符串,字符串不存在提示错误。

代码

#include<bits/stdc++.h>
using namespace std;
const int bas=26;//字符集数量
#define dt(c,n,s) Data_type(c,n,s)
struct Data_type{
    char c;//字符
    int num;//出现次数
    int s;//作为词尾出现的次数
    Data_type(){};
    Data_type(char tc, int tnum, int ss){
        c=tc;   num=tnum;   s=ss;
    }
};
struct node{
    Data_type data;
    node *a[bas];
};
void add_node(node *s, Data_type x){
    node *temp=new node;
    temp->data= x;
    for(int i=0;i<bas;i++){
        temp->a[i]=NULL;
    }
    s->a[x.c-'a']=temp;
}
struct tire{
    node *root;
    void init(){
        root=new node;
        root->data.num=0;
        root->data.s=0;
        for(int i=0;i<bas;i++){
            root->a[i]=NULL;
        }
    }
    int add_string(string s){//插入字符串s并返回插入后s出现的次数
        node *now=root;
        now->data.num++;
        for(int i=0;i<s.length();i++){
            if(now->a[s[i]-'a']==NULL){
                add_node(now,dt(s[i],0,0));
            }
            now=now->a[s[i]-'a'];
            now->data.num++;
            now->data.c=s[i];
        }
        now->data.s++;
        return now->data.s;
    }
    int add_string(char *s){
        int n=strlen(s);
        node *now=root;
        for(int i=0;i<n;i++){
            if(now->a[s[i]-'a']==NULL){
                add_node(now,dt(s[i],0,0));
            }
            now=now->a[s[i]-'a'];
            now->data.num++;
            now->data.c=s[i];
        }
        now->data.s ++;
        return now->data.s;
    }
    int query(string s){
        node *now=root;
        for(int i=0;i<s.length();i++){
            if(now->a[s[i]-'a']==NULL) return 0;
            now=now->a[s[i]-'a'];
        }
        return now->data.s;
    }
    int query(char *s){
        node *now=root;
        int n=strlen(s);
        for(int i=0;i<n;i++){
            if(now->a[s[i]-'a']==NULL) return 0;
            now=now->a[s[i]-'a'];
        }
        return now->data.s;
    }
    void del(node *h, char *s, int t){//从头删除
        if(s[0]=='\0'||h==NULL) {
            h->data.num -=t;
            h->data.s -=t;
            if(h->data.num==0)free(h);
            return;
        }
        del(h->a[s[0]-'a'], s+1, t);
        if(h->a[s[0]-'a']->data.num==0){
            h->a[s[0]-'a']=NULL;
        }
    }
    int del(char *s, int t){//删除t个字符串s,返回实际删除个数
        int ret=t, n=strlen(s);
        if(n==0)return t;//字符串为空则直接返回
        node *now=root;
        for(int i=0;i<n;i++){
            if(now->a[s[i]-'a']==NULL)return 0;//字符串在树中不存在,删除失败
            now=now->a[s[i]-'a'];
        }
        ret=min( t, now->data.s);
        del(root, s, ret);
        return ret;
    }
    char pr[100052]={0};//字符串最大长度
    void dfs(node *x,int len){
        if(x->data.s!=0){
            for(int i=0;i<len;i++){
                printf("%c",pr[i]);
            }
            printf(" (*%d)\n",x->data.s);
        }
        for(int i=0;i<bas;i++){
            if(x->a[i]==NULL)continue;
            pr[len]=x->a[i]->data.c;
            dfs(x->a[i],len+1);
        }
    }
    void print(){//打印字典树中所有字符串
        dfs(root,0);
    }
};
char s[10000];
int op;
int main(){
    tire tr;
    tr.init();
    while(1){
        scanf("%d",&op);
        if(op==0){
            scanf("%s",s);
            tr.add_string(s);
        }
        if(op==1){
            tr.print();
        }
        if(op==2){
            scanf("%s",s);
            printf("num= %d\n",tr.query(s));
        }
        if(op==3){
            scanf("%s",s);
            int ans=tr.del(s,1);
            if(ans==0) printf("error\n");
            else printf("successful\n");
        }
    }
    return 0;
}

待加功能:

5.返向连接Fail 边,跑 AC自动机 匹配字符串。