标签:std AC Trie int 数组 字符串 自动机 节点
字符串算法,随便学一下。
Trie树
字典树,用来求前缀的匹配。
比较简单,每一个字符都是一个节点,相同字符都是相同节点,然后就完了。
我们可以设这里插入的字符串分别是
abc
cab
bac
bca
这就是 Trie 构造出来的样子,是不是一下就懂了?我们查询的时候根据这个树跳就完了。
代码也很好实现,用一个结构体存,也可以用多个数组。
一个二位数组表示这个点的下一个点是什么,一维表示当前节点编号,另一维开好所有可能出现字符情况。
可能说的不是很清楚,举个例子,假设这个插入的字符串中只有 26 个英文字母,那我们就开 26 个数组,用这样提前开好的方式来存,同样的,如果有同时包含了大小写字母,那我们就可以开 52。
再来一个数组表示当前节点是否是一个单词结束的点。
这里直接给出代码:
给个模板题
constexpr int M = 65;
constexpr int N = 3E6 + 10;
struct node {
int nxt[M];
} t[N];
int tag[N];
int trun(char c) {
if (c >= 'a' && c <= 'z') return c - 'a';
if (c >= 'A' && c <= 'Z') return c - 'A' + 26;
return c - '0' + 52;
}
int idx = 0;
void insert(std::string s) {
int n = s.size();
int p = 0;
for (int i = 0; i < n; i++) {
// std::cout << p << "\n";
int c = trun(s[i]);
if (!t[p].nxt[c]) {
t[p].nxt[c] = ++idx;
}
p = t[p].nxt[c];
tag[p]++;
}
}
int query(std::string s) {
int n = s.size(), p = 0;
for (int i = 0; i < n; i++) {
int c = trun(s[i]);
if (!t[p].nxt[c]) return 0;
p = t[p].nxt[c];
}
return tag[p];
}
void solve() {
int n, q;
std::cin >> n >> q;
for (int i = 0; i <= idx; i++) for (int j = 0; j < M; j++) t[i].nxt[j] = 0;
for (int i = 0; i <= idx; i++) tag[i] = 0;
idx = 0;
for (int i = 0; i < n; i++) {
std::string s;
std::cin >> s;
insert(s);
}
while (q--) {
std::string s;
std::cin >> s;
std::cout << query(s) << "\n";
}
}
标签:std,AC,Trie,int,数组,字符串,自动机,节点 来源: https://www.cnblogs.com/Zheng-XiangYu/p/16557741.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。