voidinsert(string &s) { int p = 0; for (int i = 0; i < s.size(); i++) { int c = s[i] - 'a'; if (trie[p][c] == 0) trie[p][c] = ++idx; //没有节点,创造节点,指定在栈空间的位置 p = trie[p][c]; //更新当前位置,进入c节点 } counts[p]++; //更新计数 }
intquery(string &s) { int p = 0; for (int i = 0; i < s.size(); i++) { int c = s[i] - 'a'; if (!trie[p][c]) return0; p = trie[p][c]; } return counts[p]; }
intmain(int argc, char **argv) { for (int i = 0; i < 5; i++) { string s; cin >> s; insert(s); }
for (int i = 0; i < 5; i++) { string s; cin >> s; cout << query(s) << endl; }
structtrieNode { int son[26] = {0}; int counts = 0; int fail = -1; };
voidinsert(const string &s, vector<trieNode> &trie) { int p = 0; for (int i = 0; i < s.size(); i++) { int cha = s[i] - 'a'; if (!trie[p].son[cha]) trie[p].son[cha] = ++idx; p = trie[p].son[cha]; } trie[p].counts++; }
voidbuild_fail(vector<trieNode> &trie) { queue<int> q; for (int i = 0; i < 26; i++) { if (trie[0].son[i] != 0) { //儿子节点 int son = trie[0].son[i]; trie[son].fail = 0; //第一层 fail q.push(son); } }
while (q.size()) { int father = q.front(); q.pop(); for (int i = 0; i < 26; i++) { if (trie[father].son[i] != 0) { int cur = trie[father].son[i]; // 要找fail的儿子 int failOfFather = trie[father].fail; // 父节点的fail // ~(0): -1, ~(-1): 0 //不是根节点且没有找到目标同字符 while (~failOfFather && !trie[father].son[i]) failOfFather = trie[failOfFather].fail;
intquery(const string &s, vector<trieNode> &trie) { int ans = 0; int ptr = 0; for (int i = 0; i < s.size(); i++) { int word = s[i] - 'a'; // 儿子不存在且fail不是根节点,跳转 fail while (!trie[ptr].son[word] && ~trie[ptr].fail) ptr = trie[ptr].fail; if (trie[ptr].son[word]) // 儿子存在,匹配,进入节点,继续查找 ptr = trie[ptr].son[word]; else// 是根节点,下一个 s 字符 continue;
int ptr_temp = ptr; // copt ptr,ptr为回溯位置 while (~trie[ptr_temp].fail) //到根节点退出,下一个外层for回溯 { ans += trie[ptr_temp].counts; // counts在不是目标处为0 ptr_temp = trie[ptr_temp].fail; } } return ans; }