Trie 板子

#include <bits/stdc++.h>
using namespace std;

const int N=2e5+10;
const int root=0;    // 默认 Trie 根节点位置为 0
/* trie[i][j] i 记录当前节点位置, 同样只关注指向下一个节点的相对位置, j 是表征当前节点下一个字母的指针
   合起来是当前节点为 i 下一个字母对应编码为 j 的下一个节点的位置为 trie[i][j]
   当前树只存储 26 位小写字母构成的string
*/
int trie[N][26];  // 存储 Trie
int sz=0;   // Trie 大小
int val[N]; // Trie 节点信息

void init(){
    sz=1;
    memset(trie,0,sizeof(trie));
    memset(val,0,sizeof(val));
}

// 将字符串插入 Trie
void insert_str(const string str){
    int ch,pos=root;
    for(int i=0;i<str.size();i++){
        ch=str[i]-'a';
        if(!trie[pos][ch]) trie[pos][ch]=++sz;
        pos=trie[pos][ch];
    }
    val[pos]=1;
    /* val[pos] 的更新
       可以放到 for 循环内,也可以放到 for 循环外面,根据不同的题有不同的方法.
       当在 for 循环内部时,用来表示的含义时 相同的前缀出现的次数.
       当在外面的时候给 val 变成 1 或 -1 表示这个串到这里结束。
    */
}

// 查询字符串 str 是否出现过
bool query_str(const string str){
    int ch,pos=root;
    for(int i=0;i<str.size();i++){
        ch=str[i]-'a';
        if(!trie[pos][ch]) return false;
        pos=trie[pos][ch];
    }
    return val[pos];
}

int main()
{
    ios::sync_with_stdio(0);
    clock_t c1 = clock();
#ifdef LOCAL
    freopen("data.in","r",stdin);
    freopen("data.out","w",stdout);
#endif
    // ======================================================================
    int n,q;
    string tmp;
    init();
    cin>>n>>q;
    while(n--){
        cin>>tmp; insert_str(tmp);
    }
    while(q--){
        cin>>tmp;
        if(query_str(tmp)) puts("Existed!");
        else puts("Not yet!");
    }

    // ======================================================================
end:
    cerr << "Time Used:" << clock() - c1 << "ms" << endl;
    return 0;
}
/*
输入:
7 2
dgsdbc
zfhdfaaa
absfs
xbcc
vbgdch
syqwq
fgwctc
syqwq
fgwsyq

输出:
Existed!
Not yet!


*/

上一篇:字典树


下一篇:洛谷 P5231 [JSOI2012]玄武密码