字典树入门

hdu 1251

题意:将一系列字符串插入字典中之后,查询给定的字符串是多少字符串的前缀。

思路:裸字典树

PS:很坑,用指针写无限MLE,只能用数组写了,不知道要开多大,一直照着内存改。

数组版本:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
typedef long long ll;
#define clr(x,y) memset(x,y,sizeof x)
#define INF 0x3f3f3f3f
const ll Mod = 1e9 + 7;
typedef pair<ll,ll> P;

char s[20];
int trie[maxn * 4][26];
int num[maxn * 4];
int tot = 1;
void inserts(char* s)
{
    int root = 1;
    for(int i = 0;s[i];i ++)
    {
        int x = s[i] - 'a';
        if(trie[root][x] == 0)
            trie[root][x] = ++ tot;
        root = trie[root][x];
        num[root] ++;
    }
}
int finds(char *s)
{
    int root = 1;
    for(int i = 0;s[i];i ++)
    {
        int x = s[i] - 'a';
        if(trie[root][x] == 0)
            return 0;
        root = trie[root][x];
    }
    return num[root];
}
int main()
{
    bool flag = false;
    clr(trie,0);clr(num,0);
    while(gets(s))
    {
        int len = strlen(s);
        if(len == 0)
        {
            flag = true;continue;
        }
        if(!flag)
        {
            inserts(s);
        }
        else
        {
            printf("%d\n",finds(s));
        }
    }
    return 0;
}

MLE的指针版本:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 50000 + 10;
typedef long long ll;
#define clr(x,y) memset(x,y,sizeof x)
#define INF 0x3f3f3f3f
const ll Mod = 1e9 + 7;
typedef pair<int,int> P;


struct Trie 
{
    int cnt;
    Trie * next[26];
}* root;

Trie* build()
{
    Trie *t = new Trie();
    memset(t -> next,NULL,sizeof(t -> next));
    t -> cnt = 0;
    return t;
}

void inserts(char *s)
{
    Trie *rt = root;
    while((*s))
    {
        int x = (*s) - 'a';
        if(rt -> next[x] == NULL)
            rt -> next[x] = build();
        rt = rt -> next[x];
        rt -> cnt ++;
        s ++;
    }
}
int finds(char *s)
{
    Trie * rt = root;
    while((*s))
    {
        int x = (*s) - 'a';
        if(rt -> next[x] == NULL)
            rt -> next[x] = build();
        rt = rt -> next[x];
        s ++;
    }
    return rt -> cnt;
}
int main()
{
    root = build();
    bool flag = false;
    char s[10];
    while(gets(s))
    {
        int len = strlen(s);
        if(len == 0)
        {
            flag = true;continue;
        }
        if(!flag)
        {
            inserts(s);
        }
        else
        {
            printf("%d\n",finds(s));
        }
    }
    return 0;
}
hdu 1247 

题意:查询一个单词能够分成两部分,这两部分在字典中的单词。

思路:查询成两部分,在字典树中查询。主要查询的是出现过的单词,而不是单词前缀。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 50000 + 10;
typedef long long ll;
#define clr(x,y) memset(x,y,sizeof x)
#define INF 0x3f3f3f3f
const ll Mod = 1e9 + 7;
typedef pair<int,int> P;

char s[maxn][20];
int trie[maxn * 4][26];
int tot = 1;
int vis[maxn * 4];
void inserts(char* s)
{
    int root = 1;
    for(int i = 0;s[i];i ++)
    {
        int x = s[i] - 'a';
        if(trie[root][x] == 0)
            trie[root][x] = ++ tot;
        root = trie[root][x];
    }
    vis[root] = 1;
}
int find2(char *s)
{
    int root = 1;
    for(int i = 0;s[i];i ++)
    {
        int x = s[i] - 'a';
        if(trie[root][x] == 0)
            return 0;
        root = trie[root][x];
    }
    if(vis[root])return 1;
    return 0;
}
int find1(char *s)
{
    int root = 1;
    for(int i = 0;s[i];i ++)
    {
        int x = s[i] - 'a';
        if(trie[root][x] == 0)
            return 0;
        root = trie[root][x];
        if( s[i + 1] && vis[root] && find2(s + i + 1))
            return 1;
    }
    return 0;
}
int main()
{
    int len = 0;clr(trie,0);clr(vis,0);
    while( ~ scanf("%s",s[++ len])){inserts(s[len]);}

    for(int i = 1;i <= len;i ++)
    {
        if(find1(s[i]))
            printf("%s\n",s[i]);
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/xiaolonggezte/article/details/79158568