【Trie字典树】ZOJ 3228

本文介绍了一种利用Trie树解决字符串匹配问题的方法,通过构建Trie树并进行深度枚举,实现了对主串中长度为6的子串进行匹配分析,解决了实际编程中的复杂性问题。

这题看了一个解题报告说可以不用自动机做,单用trie树就可以过,于是就做做呗。

思路是这样的:因为每个模式串长度不超过6,所以可以建一棵6层的trie树,从主串的第一个开始枚举长度为6的字串建树,树节点有三个数据域,一个是next数组指向下一个字母,一个是over代表到达当前字母所形成的串可以覆盖的出现次数,notover代表不可以覆盖的次数,last_pos代表当前字母上一次的位置,用于不覆盖情况用的。接着就乱搞,NND,指针竟然爆内存!!!只好改用数组

#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <time.h>
#include <cstdio>
#include <math.h>
#include <iomanip>
#include <cstdlib>
#include <limits.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;

#define LL long long
#define MIN INT_MIN
#define MAX INT_MAX
#define PI acos(-1.0)
#define FRE freopen ("input.txt","r",stdin)
#define FF  freopen ("output.txt","w",stdout)
#define N 100005
char str[N];
struct node {
    int next[26];
    int over;
    int notover;
    int last_pos;
}p[400000];
int kk;
void init(int pos) {
    int i;
    for (i = 0 ;i < 26; i++)p[pos].next[i] = -1;
    p[pos].last_pos = -1;
    p[pos].notover = 0;
    p[pos].over = 0;
}
void Build(char *s,int st) {
    int pos = 0;
    int i;
    for (i = 0; s[i]; i++) {
        int id = s[i] - 'a';
        if (p[pos].next[id] == -1) {
            init(kk);
            p[pos].next[id] = kk++;
        }   pos = p[pos].next[id];
            if (p[pos].last_pos < st) {
                p[pos].notover++;
                p[pos].last_pos = st+i;
            }
            p[pos].over++;

    }
}
int gao(int op,char *s) {
    int pos = 0;
    int i;
    int sum = 0;
    for (i = 0; s[i]; i++) {
        int id = s[i] - 'a';
        if (p[pos].next[id] != -1) {
            pos = p[pos].next[id];
        } else return 0;
    }
    if (!op) {
        sum += p[pos].over;
    } else {
        sum += p[pos].notover;
    }
    return sum;
}

int main () {  
    char ss[7];
    int ca = 1;
    while (scanf("%s",str) !=EOF) {
        int n;
        int i,j;
        int len = strlen(str);
        init(0);
        int cnt;
        kk = 1;
        for (i = 0; str[i]; i++) {
            cnt = 0;
            for (j = i; j < i + 6 && j < len; j++) {
                ss[cnt++] = str[j];
            }
            ss[cnt] = '\0';
            Build(ss,i);
        }
        scanf("%d",&n);
        printf("Case %d\n",ca++);
        while (n--) {
            int op;
            scanf("%d%s",&op,ss);
            printf("%d\n",gao(op,ss));
        }
        puts("");
    }
    return 0;
}



贴一个指针爆内存版

#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <time.h>
#include <cstdio>
#include <math.h>
#include <iomanip>
#include <cstdlib>
#include <limits.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;

#define LL long long
#define MIN INT_MIN
#define MAX INT_MAX
#define PI acos(-1.0)
#define FRE freopen ("input.txt","r",stdin)
#define FF  freopen ("output.txt","w",stdout)
#define N 100005
char str[N];
struct node {
    node *next[26];
    int over;
    int notover;
    int last_pos;
    node () {
        memset(next,NULL,sizeof(next));
        over = 0;
        notover = 0;
        last_pos = -1;
    };
};
void Build(char *s,node *root,int st) {
    node *p;
    p = root;
    int i;
    for (i = 0; s[i]; i++) {
        int id = s[i] - 'a';
        if (p->next[id] == NULL) {
            p->next[id] = new node ;
        }
            if (p->next[id]->last_pos < st) {
                p->next[id]->notover++;
                p->next[id]->last_pos = st+i;
            }
            p->next[id]->over++;
            p = p->next[id];
    }
}
int gao(int op,char *s,node *root) {
    node *p;
    p = root;
    int i;
    int sum = 0;
    for (i = 0; s[i]; i++) {
        int id = s[i] - 'a';
        if (p->next[id]) {
            p = p->next[id];
        } else return 0;
    }
    if (!op) {
        sum += p->over;
    } else {
        sum += p->notover;
    }
    return sum;
}

int main () {  
    char ss[7];
    int ca = 1;
    while (scanf("%s",str) !=EOF) {
        int n;
        int i,j;
        int len = strlen(str);
        node *root = new node();
        int cnt;
        for (i = 0; str[i]; i++) {
            cnt = 0;
            for (j = i; j < i + 6 && j < len; j++) {
                ss[cnt++] = str[j];
            }
            ss[cnt] = '\0';
            Build(ss,root,i);
        }
        scanf("%d",&n);
        printf("Case %d\n",ca++);
        while (n--) {
            int op;
            scanf("%d%s",&op,ss);
            printf("%d\n",gao(op,ss,root));
        }
        puts("");
    }
    return 0;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值