也许你的第一个想法是暴力搜索每一个单词,但是复杂度很很很很高啊
有一种东西叫做字典树,字典树的根节点连出来的每一条边存的就是出现的首字母,
然后但此后边的字母我们可以在后边存上, 这样每一个单词的最后一个单词就是最后存的
那条边,这样我们可以在那条代表着最后单词的边的下一个节点处打一个标记,然后表示一个单词就结束了;
like this
把每一个单词放到字典树中...
void add(string ch) {
int len = ch.size(), root = 0, x;
for (int i = 0; i < len; i++) {
x = ch[i] - 'a';
if (!trie[root][x]) trie[root][x] = ++tot;
tr[trie[root][x]] = 1;
root = trie[root][x];
}
tr[trie[root][x]] = 1;
}
int query(string ch) {
int len = ch.size(), root = 0, ans = 0;
int x;
for (int i = 0; i < len; i++) {
x = ch[i] - 'a';
if (trie[root][x] == 0) return 0;
ans = tr[trie[root][x]];
tr[trie[root][x]] = 2;
root = trie[root][x];
}
return ans;
}
上代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int tot, trie[400001][31], tr[400001];
string ch;
void add(string ch) {
int len = ch.size(), root = 0, x;
for (int i = 0; i < len; i++) {
x = ch[i] - 'a';
if (!trie[root][x]) trie[root][x] = ++tot;
tr[trie[root][x]] = 1;
root = trie[root][x];
}
tr[trie[root][x]] = 1;
}
int query(string ch) {
int len = ch.size(), root = 0, ans = 0;
int x;
for (int i = 0; i < len; i++) {
x = ch[i] - 'a';
if (trie[root][x] == 0) return 0;
ans = tr[trie[root][x]];
tr[trie[root][x]] = 2;
root = trie[root][x];
}
return ans;
}
int main() {
int n, m;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
cin>>ch;
add(ch);
}
scanf("%d", &m);
for (int i = 1; i <= m; i++) {
cin >> ch;
if (query(ch) == 1) printf("OK\n");
else if (query(ch) == 0) printf("WRONG\n");
else if (query(ch) == 2) printf("REPEAT\n");
}
}
还是看不懂的小伙伴们看这里
may be 这个比我都讲得好
原文:https://www.cnblogs.com/zzz-hhh/p/11215774.html