感觉不把这个Trie理解一下,AC自动机的代码看起来有点费劲。

这里代码的学习仿照训练指南209页。

这里如果只是查询单词,感觉用map更好,但是如果查前缀,还是用Trie。

1、Trie查询前缀字符串是否存在。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define mst(s,v) memset(s, v, sizeof(s));
  4. const int maxnode = ;
  5. const int sigma_size = ;
  6. //字母表为全体小写字母的Trie
  7. struct Trie{
  8. int ch[maxnode][sigma_size];
  9. int val[maxnode];
  10. int sz; //结点总数
  11. Trie(){ sz=; mst(ch[], ); mst(val, ); } //初始时只有一个根节点
  12. int idx(char c) { return c-'a'; }
  13. //插入字符串s,附加信息为v。v!=0(0代表本身不是单词结点)
  14. void insert(char *s, int v){
  15. int u = , n = strlen(s);
  16. for(int i=; i<n; i++){
  17. int c = idx(s[i]);
  18. if(!ch[u][c]){ //结点不存在
  19. memset(ch[sz], , sizeof(ch[sz]));
  20. val[sz] = ; //中间结点的附加信息为0
  21. ch[u][c] = sz++;
  22. }
  23. u = ch[u][c];
  24. }
  25. val[u] = v; //字符串的最后一个字符的附加信息
  26. //标记在末结点,查询整个单词时有用
  27. }
  28. bool find(char *s){
  29. int u = , len = strlen(s);
  30. for(int i=; i<len; i++){
  31. int c = idx(s[i]);
  32. if(!ch[u][c]) return false;
  33. u = ch[u][c];
  34. }
  35. return true; //查询整个单词时 return val[u]
  36. }
  37. }tree;
  38. int main(){
  39. freopen("in.txt", "r", stdin);
  40. int n, m;
  41. cin >> n >> m;
  42. char tmp[];
  43. for(int i=; i<n; i++){
  44. cin >> tmp;
  45. cout << tmp << endl;
  46. tree.insert(tmp, );
  47. }
  48. for(int i=; i<m; i++){
  49. cin >> tmp;
  50. cout << endl << tmp << endl;
  51. if(tree.find(tmp)) cout << "Y" << endl;
  52. else cout << "N" << endl;
  53. }
  54. return ;
  55. }
  56. /*
  57. 6 2
  58. shex
  59. shexy
  60. yasherhs
  61. say
  62. shrxy
  63. sher
  64. yasherhs
  65. she
  66. */

2、Trie查询前缀个数

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define mst(s,v) memset(s, v, sizeof(s));
  4. const int maxnode = ;
  5. const int sigma_size = ;
  6. //可以查找前缀,也可以查找单词(map)
  7. struct Trie{
  8. int ch[maxnode][sigma_size];
  9. int sum[maxnode];
  10. int sz; //结点总数
  11. Trie(){ sz=; mst(ch[], ); mst(sum, ); }
  12. int idx(char c) { return c-'a'; }
  13. //插入字符串s,附加信息为v。v!=0(0代表本身不是单词结点)
  14. void insert(char *s){
  15. int u = , n = strlen(s);
  16. for(int i=; i<n; i++){
  17. int c = idx(s[i]);
  18. if(!ch[u][c]){ //结点不存在
  19. memset(ch[sz], , sizeof(ch[sz]));
  20. ch[u][c] = sz++;
  21. }
  22. sum[ch[u][c]]++;
  23. u = ch[u][c];
  24. }
  25. }
  26. int find(char *s){
  27. int u = , len = strlen(s);
  28. for(int i=; i<len; i++){
  29. int c = idx(s[i]);
  30. if(!ch[u][c]) return ;
  31. u = ch[u][c];
  32. }
  33. return sum[u];
  34. }
  35. }tree;
  36. int main(){
  37. freopen("in.txt", "r", stdin);
  38. int n, m;
  39. cin >> n >> m;
  40. char tmp[];
  41. for(int i=; i<n; i++){
  42. cin >> tmp;
  43. tree.insert(tmp);
  44. }
  45. for(int i=; i<m; i++){
  46. cin >> tmp;
  47. cout << tmp << endl;
  48. cout << tree.find(tmp) << endl;
  49. }
  50. return ;
  51. }

3、用指针理解Trie

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define mst(s,v) memset(s, v, sizeof(s));
  4. const int sigma_size = ;
  5. struct node{
  6. int count;
  7. node * next[];
  8. }*root;
  9. int idx(char c){ return c-'a'; }
  10. node* build(){
  11. node* k = new(node);
  12. k->count = ;
  13. mst(k->next , );
  14. return k;
  15. }
  16. void insert(char* s){
  17. node* r = root;
  18. char* word = s;
  19. while(*word){
  20. int c = idx(*word);
  21. if(r->next[c] == NULL) r->next[c] = build();
  22. r = r->next[c];
  23. r->count++;
  24. word++;
  25. }
  26. }
  27. int find(char* s){
  28. node* r = root;
  29. char* word = s;
  30. while(*word){
  31. int c = idx(*word);
  32. r = r->next[c];
  33. if(r==NULL) return ;
  34. word++;
  35. }
  36. return r->count;
  37. }
  38. int main(){
  39. freopen("in.txt", "r", stdin);
  40. int n, m;
  41. cin >> n >> m;
  42. char tmp[];
  43. root = build();
  44. for(int i=; i<n; i++){
  45. cin >> tmp;
  46. insert(tmp);
  47. }
  48. for(int i=; i<m; i++){
  49. cin >> tmp;
  50. cout << tmp << endl;
  51. cout << find(tmp) << endl;
  52. }
  53. return ;
  54. }

Trie灵活的地方是在插入时对点的属性的更新,以及查询时与其他算法的结合。

这里将AC自动机summer-work那里的C - L语言拿过来,感受在查询变化的一些思路。

题意:n(1,20)模式串(可以有包含关系(这就决定了不能贪心)),m(1,20)文本串,对每个文本串,n个模式串最多可以组成的最长前缀的位置。

这题就是在find()上思考解法,正解应该是dp[i]是否能理解前i个单词,这里因为是学习Trie,所以就暴力吧(感觉自己太水)。

这里总结一个套路,因为是单词而非前缀,所以insert()时点的属性是val=1。

为了创造vis(是否理解前i个单词)的边界条件vis[0]=v(明显可以识别),所以这里scanf(s+1),即遍历时从i+1开始。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define mst(s,v) memset(s, v, sizeof(s));
  4. const int maxnode = ;
  5. const int sigma_size = ;
  6. const int maxlen = 1e6 + 5e4;
  7. int dp[maxlen];
  8. struct Trie{
  9. int ch[maxnode][sigma_size];
  10. int val[maxlen];
  11. int sz;
  12. Trie(){ sz=; }
  13. inline int idx(char c) { return c-'a'; }
  14. inline void insert(char *s){
  15. int u = , n = strlen(s);
  16. for(int i=; i<n; i++){
  17. int c = idx(s[i]);
  18. if(!ch[u][c]){
  19. ch[u][c] = sz++;
  20. }
  21. u = ch[u][c];
  22. }
  23. val[u] = ; //标记单词
  24. }
  25. inline int find(char *s, int v){
  26. int u = , len = strlen(s), ans = ;
  27. dp[] = v; //标记能够被识别的前缀位置
  28. for(int i=; i<len; i++){
  29. if(dp[i] == v){
  30. u = ;
  31. for(int j=i+; j<len; j++){
  32. int c = idx(s[j]);
  33. if(!ch[u][c]) break;
  34. //cout<<"u = "<<u<<" v = "<<v<<" s[j] = "<<s[j]<<endl;
  35. u = ch[u][c];
  36. if(val[u]){ //找到单词的前缀
  37. ans = max(ans, j);
  38. dp[j] = v; //标记位置
  39. }
  40. }
  41. }
  42. }
  43. return ans;
  44. }
  45. }tree;
  46. char tmp[maxlen];
  47. int main(){
  48. // freopen("in.txt", "r", stdin);
  49. int n, m;
  50. scanf("%d%d", &n, &m);
  51. for(int i=; i<n; i++){
  52. scanf("%s", tmp);
  53. tree.insert(tmp);
  54. }
  55. for(int i=; i<=m; i++){
  56. scanf("%s", tmp+);
  57. printf("%d\n", tree.find(tmp, i));
  58. }
  59. return ;
  60. }

Trie代码学习的更多相关文章

  1. u-boot代码学习内容

    前言  u-boot代码庞大,不可能全部细读,只能有选择的读部分代码.在读代码之前,根据韦东山教材,关于代码学习内容和深度做以下预先划定. 一.Makefile.mkconfig.config.mk等 ...

  2. Objective-C代码学习大纲(3)

    Objective-C代码学习大纲(3) 2011-05-11 14:06 佚名 otierney 字号:T | T 本文为台湾出版的<Objective-C学习大纲>的翻译文档,系统介绍 ...

  3. ORB-SLAM2 论文&代码学习 ——Tracking 线程

    本文要点: ORB-SLAM2 Tracking 线程 论文内容介绍 ORB-SLAM2 Tracking 线程 代码结构介绍 写在前面 上一篇文章中我们已经对 ORB-SLAM2 系统有了一个概览性 ...

  4. ORB-SLAM2 论文&代码学习 —— 单目初始化

    转载请注明出处,谢谢 原创作者:Mingrui 原创链接:https://www.cnblogs.com/MingruiYu/p/12358458.html 本文要点: ORB-SLAM2 单目初始化 ...

  5. ORB-SLAM2 论文&代码学习 —— LocalMapping 线程

    转载请注明出处,谢谢 原创作者:Mingrui 原创链接:https://www.cnblogs.com/MingruiYu/p/12360913.html 本文要点: ORB-SLAM2 Local ...

  6. Learning Memory-guided Normality代码学习笔记

    Learning Memory-guided Normality代码学习笔记 记忆模块核心 Memory部分的核心在于以下定义Memory类的部分. class Memory(nn.Module): ...

  7. 3.1.5 LTP(Linux Test Project)学习(五)-LTP代码学习

    3.1.5 LTP(Linux Test Project)学习(五)-LTP代码学习 Hello小崔 ​ 华为技术有限公司 Linux内核开发 2 人赞同了该文章 LTP代码学习方法主要介绍两个步骤, ...

  8. Apollo代码学习(七)—MPC与LQR比较

    前言 Apollo中用到了PID.MPC和LQR三种控制器,其中,MPC和LQR控制器在状态方程的形式.状态变量的形式.目标函数的形式等有诸多相似之处,因此结合自己目前了解到的信息,将两者进行一定的比 ...

  9. Dagger2 生成代码学习

    接上一篇文章介绍了Dagger2的初步使用,相信刚接触的人会觉得很奇怪,怎么会有很多自己没有定义的代码出现,为什么Component的创建方式是那样的.为了搞清楚这些东西,我们需要查看一下Dagger ...

随机推荐

  1. CSP2019 退役记

    本来想写"退役在即"的,考完 Day2 后直接改成"退役记"了 Day 0 在 ssf 的机房里继续变弱,自己写了一遍 splay 板子,居然写对了,开心 非常 ...

  2. [唐胡璐]Selenium技巧- IEDriverServer在进程中没有关闭?

    有时候跑完脚本后,IEDriverServer.exe进程没杀掉。 解决方法: 在关闭driver时用Driver.Quit();不要用Driver.Close();Driver.Quit() Qui ...

  3. css3 制作圆环进度条

    引子 移动端做一个 loadiing 加载的图标,跟以往沿用的都不太一样,是一个圆环进度条,圆环进度条也就罢了,还得能用百分比控制. CSS3 实现圆环 demo 刚开始写这个圆环的时候是参照帖子上给 ...

  4. Linq 分组查询

    根据部门分组 ,然后存储部门下所有员工 public class Custom { public string dname { get; set; } public List<Employees ...

  5. Qt 程序自动重启的实现

    正常退出调用exit() 或quit()就行,想要自已重启可按下面代码: void XXX:onRestart() { //类中调用 qApp->exit(); } 主main函数中处理 int ...

  6. Codeforces Round #589 (Div. 2) C - Primes and Multiplication(数学, 质数)

    链接: https://codeforces.com/contest/1228/problem/C 题意: Let's introduce some definitions that will be ...

  7. SQL Update多表联合更新的方法

    SQL Update多表联合更新的方法 (1) sqlite 多表更新方法 update t1 set col1=t2.col1 from table1 t1 inner join table2 t2 ...

  8. luogu P1494 [国家集训队]小Z的袜子 ( 普 通 )

    题目:    链接:https://www.luogu.org/problemnew/show/P1494 题意:一些袜子排成一排,每个袜子有固定的颜色.                        ...

  9. django-配置相关

    1 自己配置一个静态文件夹 settings.py中 # 用户上传的文件配置 MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'me ...

  10. Centos7安装Redis5.0.3

    1.切换目录 cd tmp 2.下载 wget http://download.redis.io/releases/redis-5.0.3.tar.gz 3.解压,删除压缩包 tar xzf redi ...