Tire树相关

tire树用来快速查找一组字符串。

算法流程

int son[N][26], cnt[N], idx;
char str[N];

// 插入和删除类似,每次从根节点入场,采用计数方法,0表示没有此节点,1表示存在节点。
void insert(char* str) { int p = 0; for(int i = 0; str[i]; i ++ ) { int u = str[i] - 'a'; if(!son[p][u]) son[p][u] = ++ idx;   // 没有节点,创建节点 p = son[p][u]; } cnt[p] ++ ;  // 记录这个单词出现次数 } int query(char* str) { int p = 0; for(int i = 0; str[i]; i ++ ) { int u = str[i] - 'a'; if(!son[p][u]) return 0;  // 如果没有节点直接return p = son[p][u]; } return cnt[p];  // 返回单词出现次数 }

 

 

 

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

using namespace std;

const int N = 2e5 + 10;

int n;
int son[N][26], cnt[N], idx;
char str[N];

void insert(char* str)
{
    int p = 0;
    for(int i = 0; str[i]; i ++ )
    {
        int u = str[i] - 'a';
        if(!son[p][u]) son[p][u] = ++ idx;
        p = son[p][u];
    }
    cnt[p] ++ ;
}

int query(char* str)
{
    int p = 0;
    for(int i = 0; str[i]; i ++ )
    {
        int u = str[i] - 'a';
        if(!son[p][u]) return 0;
        p = son[p][u];
    }
    return cnt[p];
}

int main()
{
    cin >> n;
    while(n -- )
    {
        char op;
        cin >> op;
        if(op == 'I')
        {
            cin >> str;
            insert(str);
        }
        else
        {
            cin >> str;
            cout << query(str) << endl;
        }
    }
    
    return 0;
}

 

 

还有一种 01 tire常用来求最大异或和。

 

// 要找最大的异或,用二进制进行枚举,遇到0找1,遇到1找0
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int N = 1e5 + 10, M = 31 * N; int n; int a[N]; int son[M][2], idx; void insert(int x) { int p = 0; for(int i = 30; i >= 0; i -- ) { int u = x >> i & 1; if(!son[p][u]) son[p][u] = ++ idx; p = son[p][u]; } } int query(int x) { int p = 0, res = 0; for(int i = 30; i >= 0; i -- ) { int u = x >> i & 1; if(son[p][!u]) { p = son[p][!u]; res += 1 << i; } else p = son[p][u]; } return res; } int main() { int n; cin >> n; for(int i = 1; i <= n; i ++ ) { cin >> a[i]; insert(a[i]); } int res = 0; for(int i = 1; i <= n; i ++ ) res = max(res, query(a[i])); cout << res << endl; return 0; }

 

判断一个字符串是否是另一个字符串的前缀。

 

 1、快速判断是否存在一个串是当前串的前缀 (遍历路径是否存在字符串结尾)

 2、快速判断当前串是否是别的串的前缀 (如果当前串在插入过程中没有创建新节点,说明当前串是别的串的前缀)

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

using namespace std;

const int N = 100010, M = 10;

int n;
int son[N][M], idx;
int cnt[N];
string str[N];

bool insert(string str) {
    int p = 0;
    bool is_match = false, new_node = false;
    for(int i = 0; i < str.size(); i ++ ) {
        int u = str[i] - '0';
        if(!son[p][u]) son[p][u] = ++ idx, new_node = true;
        p = son[p][u];
        if(cnt[p]) is_match = true;
    }
    cnt[p] ++ ;
    
    return !is_match && new_node;
}


int main() {
    int T;
    cin >> T;
    while(T -- ) {
        memset(son, 0, sizeof son);
        idx = 0;
        memset(cnt, 0, sizeof cnt);
        
        cin >> n;
        bool res = true;
        for(int i = 0; i < n; i ++ ) {
            cin >> str[i];
            if(!insert(str[i])) res = false;
        }
        
        if(res) puts("YES");
        else puts("NO");
    }
    
    
    return 0;
}

 

 

 本题是要求快速求出某个串是不是另一个串的前缀。

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

using namespace std;

const int N = 2e5 + 10, M = 26;

string s;
int son[N][M], cnt[N], idx;
bool f[N];

void insert(string& str) {
    int p = 0;
    for(int i = str.size() - 1; i >= 0; i -- ) {
        int u = str[i] - 'A';
        if(!son[p][u]) son[p][u] = ++ idx;
        p = son[p][u];
    }
    cnt[p] ++ ;
}

bool query(int ed) {
    int p = 0;
    for(int i = ed; i > ed - 10 && i >= 0; i -- ) {
        int u = s[i] - 'A';
        if(!son[p][u]) return false;
        else {
            p = son[p][u];
            if(cnt[p] && f[i]) return true;
        }
    }
    return false;
}

int main() {
    
    while(cin >> s, s != ".") {
        insert(s);
    }
    
    s.clear();
    string line;
    while(cin >> line) s += line;
    
    
    int res = 0;
    f[0] = true;
    for(int i = 1; i <= s.size(); i ++ ) {
        if(query(i - 1)) {
            f[i] = true;
            res = i;
        }
    }
    
    cout << res << endl;
    
    return 0;
}

 

posted @ 2023-11-21 18:55  深渊之巅  阅读(13)  评论(0编辑  收藏  举报