字典树

何为字典树:
如图所示:

 

 

每个字符有很多个分支,打黄色标记的就是字符串的结尾,所以这颗字典树中有哪些字符串呢,"ab","ay","ayf","c","cc","cd",其他的枝没有画全。 

如何存储:

 


 

顺序存储字符串:“ab”“ay”“ayf”“c”“cc”“cd”……(节点编号讲究先到先得)

数组tree[i][j]:代表i节点的第j个儿子的根编号。(获取第几个孩子可以s[i]-'a',以图中5节点举例,就是tree[0][2]=5)

数组flag[i]:为true代表到该节点为一个字符串

https://blog.csdn.net/TDD_Master/article/details/86688586

Phone List

 HDU - 1671   很多电话号码,看有没有一个号码是另一个号码的前缀

思路,看经过的路径上每个点的sum[i]值,如果都大于等于2,说明这个号码是某一个号码的前缀。

 

#include<cstdio>
#include<algorithm>
#include<cstring>

using namespace std;
const int maxm = 1e4 + 5;
const int maxm2 = 1e5 + 5;
int t, n, tot;
char ch[maxm][15];
int tree[maxm2][15],sum[maxm2];
void add(char s[]) {
    int root = 0, len = strlen(s);
    for(int i = 0; i < len; i++) {
        int id = s[i] - '0';
        if(!tree[root][id]) {
            memset(tree[tot], 0, sizeof(tree[tot]));
            sum[tot] = 0;
            tree[root][id] = tot++;
        }
        root = tree[root][id];
        sum[root]++;
    }
}
bool findx(char s[]) {
    int root = 0, len = strlen(s), num = 0;
    for(int i = 0; i < len; i++) {
        int id = s[i] - '0';
        root = tree[root][id];
        if(sum[root] >= 2) num++;
    }
    if(num == len) return true;
    return false;
}

int main() {
    scanf("%d", &t);
    while(t--) {
        scanf("%d", &n);
        tot = 1;
        memset(tree[0], 0, sizeof(tree[0]));
    //    memset(tree, 0, sizeof(tree));
    //    memset(sum, 0, sizeof(sum));
        for(int i = 0; i < n; i++) {
            scanf("%s", ch[i]);
            add(ch[i]);
        }
        int ans = 0;
        for(int i = 0; i < n; i++) {
            if(findx(ch[i])) {
    //            printf("%d\n", i);
                ans = 1;
                break;
            }
        }
        if(ans) printf("NO\n");
        else printf("YES\n");
    }


    return 0;
}

 

 

HDU 1247 Hat’s Words

看有没有单词是有其他两个单词合并起来的

 

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxm = 5e4 + 5;
const int maxm2 = 1e6 + 5;
char s[maxm][20];
int flag[maxm2], tree[maxm][27];
int tot;
void add(char ch[]) {
    int root = 0, id = 0, len = strlen(ch);
    for(int i = 0; i < len; i++) {
        id = ch[i] - 'a';
        if(!tree[root][id]) {
            memset(tree[tot], 0, sizeof(tree[tot]));
            flag[tot] = 0;
            tree[root][id] = tot++;
        }
        root = tree[root][id];
    }
    flag[root] = 1;
}


bool find2(char ch[]) {
    int root = 0, id = 0, len = strlen(ch);
    for(int i = 0; i < len; i++) {
        id = ch[i] - 'a';
        if(!tree[root][id]) return false;
        root = tree[root][id];
    }
    if(flag[root]) return true;
    else return false;
}

bool find1(char ch[]) {
    int root = 0, id = 0, len = strlen(ch);
    for(int i = 0; i < len; i++) {
        id = ch[i] - 'a';
        if(flag[root] && find2(ch + i)) return true;
        root = tree[root][id];
    }
    return false;
}

int main() {
    int ant = 0;
    tot = 1;
    memset(tree[0], 0, sizeof(tree[0]));
    while(~scanf("%s", s[ant])) {
    //    if(s[ant][0] == '#') break;
        add(s[ant]);
        ant++;
    }
    for(int i = 0; i < ant; i++) {
    //    printf("%d\n", find1(s[i]));
        if(find1(s[i])) printf("%s\n", s[i]);
    }
    return 0;
}

 

 

 Remember the Word

 UVALive - 3942 

这个题使用dp做得,一个单词,看他被输入的那些字符串组成由多少中情况,那些字符长度最多为100.

#include<cstdio>
#include<cstring>
#define maxnode int(4e5+10)
#define sigma_size int(26)
#define mod int(20071027)
using namespace std;
char tmp[200];
char st[maxnode];
int dp[maxnode];
int ch[maxnode][sigma_size];
int val[maxnode];
int sz, len;
//struct trie
//{
//    trie() {  }
    int idx(char c) { return c - 'a'; }
    void inse(char *s, int v)
    {
        int u = 0, n = strlen(s);
        for (int i = 0; i < n; i++)
        {
            int c = idx(s[i]);
            if (!ch[u][c])
            {
                memset(ch[sz], 0, sizeof(ch[sz]));
                val[sz] = 0;
                ch[u][c] = sz++;
            }
            u = ch[u][c];
        }
        val[u] = v;
    }
    int fid(char *s, int pos)
    {
        int ans = 0;
        int u = 0;
        for (int i = pos; i < len&&i<pos+100; i++)
        {
            int c = idx(s[i]);
            if (!ch[u][c]) return ans;
            u = ch[u][c];
    
if (val[u]) ans= (dp[i+1] + ans) % mod; } return ans; } //}tree; int main() { int cas=0, n; while (~scanf("%s", st)) { // tree = trie(); sz = 1; memset(ch[0], 0, sizeof(ch[0])); scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%s", tmp); inse(tmp, 1); } len = strlen(st); dp[len] = 1; for (int i = len - 1; i >= 0; i--) { dp[i] = fid(st, i); } printf("Case %d: %d\n",++cas, dp[0]); } return 0; }

 

posted @ 2019-02-15 20:06  downrainsun  阅读(191)  评论(0编辑  收藏  举报