constint N = 1e5+5; int son[N][26]; // 表示节点的子节点(题目中全是小写字母,因此最多26个子节点) int cnt[N]; // 表示以该节点作为结尾的单词的格个数(也是标记) int idx; // 当前用到的编号(和数组实现链表时含义相同),这里下标是0的点即是根节点又是空节点 char s[N]; // 读入的字符串
voidinsert(char str[]){ int p = 0; // 初始父节点为根节点编号为0 for (int i = 0; str[i]; ++i) { // 字符串结尾是0 int u = str[i] - 'a'; // 操作下一个字符,将其作为子节点 if (!son[p][u]) son[p][u] = ++idx; // 如果子节点不存在就创建,注意先加在赋值(不能写成idx++) p = son[p][u]; // 然后让新的节点作为下一步的父节点 }
cnt[p] ++; // p最终就是最后一个字母,表示单词的结尾 }
intquery(char str[]){ int p = 0; for (int i = 0; str[i]; ++i) { int u = str[i] - 'a'; // 操作下一个字符,将其作为子节点 if (!son[p][u]) return0; // 如果该节点不存在,表示没有查询的单词,直接返回0 p = son[p][u]; // 继续往子节点走 }
constint N = 3e6+5; int t, n, m; int son[N][62], cnt[N], idx; char s[N];
voidinit(){ for (int i = 0; i <= idx; ++i) for (int j = 0; j <= 62; ++j) son[i][j] = 0; for (int i = 0; i <= idx; ++i) cnt[i] = 0; idx = 0; }
intget_idx(char a){ if (a >= 'A' && a <= 'Z') return a - 'A'; if (a >= 'a' && a <= 'z') return a - 'a' + 26; return a - '0' + 52; }
voidinsert(char str[]){ int p = 0; for (int i = 0; str[i]; ++i) { int u = get_idx(str[i]); if (!son[p][u]) son[p][u] = ++idx; p = son[p][u]; cnt[p] ++; // 这道题要给每个经过节点的cnt增加,表示通过该节点的单词数量 } }
intquery(char str[]){ int p = 0; for (int i = 0; str[i]; ++i) { int u = get_idx(str[i]); if (!son[p][u]) return0; p = son[p][u]; } return cnt[p]; }
voidsolve(){ init();
cin >> n >> m; while (n -- ) { cin >> s; insert(s); }
constint N = 5e5+5; int n, m; int son[N][26], idx; bool st[N]; // 单词结尾的标记,true表示是结尾,false表示不是结尾 unordered_map<string, string> mp; // 用于存单词的状态,如:mp['ab'] = "OK",表示单词ab的查询结果为"OK" string s;
voidinsert(string str){ int p = 0; for (char c: str) { int u = c - 'a'; if (!son[p][u]) son[p][u] = ++idx; p = son[p][u]; }
st[p] = true; }
boolquery(string str){ int p = 0; for (char c: str) { int u = c - 'a'; if (!son[p][u]) returnfalse; // 没有子节点,更不会有该单词 p = son[p][u]; }