博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Keywords Search HDU2222 AC自动机模板题
阅读量:4541 次
发布时间:2019-06-08

本文共 4023 字,大约阅读时间需要 13 分钟。

ac自动机说起来很复杂,其实和kmp是一样的思路,都是寻找相同前后缀,减少跳的次数。只要理解了kmp是怎么求next数组的,ac自动机bfs甚至比knp还好写。

这里大致说一下kmp求next数组的方法吧,假设现在要求第c个字符的next值(假设这个c很大,这样画图出来比较清晰方便理解),因为遍历过程中我们已经知道了第c-1个字符的next为x(假设比c小很多),即next[c-1] = x。那就代表我们知道了a[1]—a[x]这一段和a[c-1-x]—a[c-1]这一段是相等的对吧。

那么现在有两种情况

一。a[x+1] 和 a[c]相等,那么显然变成了a[1]—a[x+1] 这一段和a[c-1-x]—a[c]这一段相等,即c位置的相同前后缀长度比c-1多了1,就是next[c-1]+1;

即原来是:

1——————————x      == c-1-x ————————————————c-1  ① 由于a[x+1] == a[c],变成了

1——————————x+1  == c-1-x——————————————————c

 

 

二。如果不相等,那么我们在1——x这一段下功夫,假设next[x] = y,即1——y == x-y——x这两段相等,注意根据①式,x-y——x == c-1-y——c-1,画个图就很清楚了,所以如果a[y+1] == a[c],那么相同前后缀长度就是y+1了。

即因为

1——————————x   ==    c-1-x————————————————c-1  

1——y    ==   x-y———x   ==    c-1-x——c-1-x+y     ==       c-1-y————c-1   由于a[y+1] == a[c],变成了

1——y+1             ==          c-1-y——————c 

那如果a[y+1] 与a[c]还是不相等怎么办?其实细心的话应该发现这是一个递归过程了——只要再找next[y],循环上面的过程就可以了,想明白这个过程再去看求next数组的代码就很容易理解了。

最后还是上这道题代码:

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 11 #define SIGMA_SIZE 26 12 #define pii pair
13 #define lson rt<<1 14 #define rson rt<<1|1 15 #define lowbit(x) (x&-x) 16 #define fode(i, a, b) for(int i=a; i>=b; i--) 17 #define foe(i, a, b) for(int i=a; i<=b; i++) 18 #define fod(i, a, b) for(int i=a; i>b; i--) 19 #define fo(i, a, b) for(int i=a; i
b ? a : b; } 25 inline LL LMin(LL a, LL b) { return a>b ? b : a; } 26 inline LL lgcd(LL a, LL b) { return b == 0 ? a : lgcd(b, a%b); } 27 inline LL llcm(LL a, LL b) { return a / lgcd(a, b)*b; } //a*b = gcd*lcm 28 inline int Max(int a, int b) { return a>b ? a : b; } 29 inline int Min(int a, int b) { return a>b ? b : a; } 30 inline int gcd(int a, int b) { return b == 0 ? a : gcd(b, a%b); } 31 inline int lcm(int a, int b) { return a / gcd(a, b)*b; } //a*b = gcd*lcm 32 const LL INF = 0x3f3f3f3f3f3f3f3f; 33 const LL lmod = 1e9+7; 34 const int mod = 10000; 35 const double eps = 1e-8; 36 const int inf = 0x3f3f3f3f; 37 const int maxk = 1e5+5; 38 const int maxm = 510*510; 39 const int maxn = 5e5+10; 40 41 struct node { 42 node *fail, *s[26]; 43 int w; 44 node() {} 45 46 void init() { 47 fail = NULL; 48 fo(i, 0, 26) s[i] = NULL; 49 w = 0; 50 } 51 }*head; 52 53 54 int n, ans; 55 char str[1000010]; 56 queue
q; 57 58 node* getfail(node* p, int x) 59 { 60 if (p->s[x] != NULL) return p->s[x]; 61 else { 62 if (p == head) return head; 63 else return getfail(p->fail, x); 64 } 65 } 66 67 void build() 68 { 69 node* root = head; 70 node* tmp; 71 72 int len = strlen(str); 73 for ( int j = 0; j < len; j++ ) 74 { 75 int k = str[j]-'a'; 76 if (root->s[k] == NULL) { 77 tmp = new node; tmp->init(); 78 tmp->fail = head; 79 root->s[k] = tmp; 80 } 81 82 root = root->s[k]; 83 //标记单词结尾 84 if (j == len-1) root->w++; 85 } 86 } 87 88 void build_ac() 89 { 90 node* r; 91 while(!q.empty()) q.pop(); 92 q.push(head); 93 while(!q.empty()) 94 { 95 r = q.front(); q.pop(); 96 fo(j, 0, 26) 97 { 98 if (r->s[j] != NULL) { 99 q.push(r->s[j]);100 if (r == head) r->s[j]->fail = head;101 else r->s[j]->fail = getfail(r->fail, j);102 }103 }104 }105 return;106 }107 108 void solve()109 {110 int len = strlen(str);111 node *tmp, *r = head;112 fo(j, 0, len)113 {114 int k = str[j]-'a';115 //找到前缀116 while( r->s[k]==NULL && r != head ) r = r->fail; 117 //自动机向下匹配118 //如果可以匹配,则进入下一节点,否则返回头节点119 r = (r->s[k]==NULL) ? head : r->s[k];120 tmp = r;121 122 //如果单词a出现,则他的前缀也全部出现过123 while(tmp != head) {124 ans += tmp->w;125 tmp->w = 0;126 tmp = tmp->fail;127 } 128 }129 return;130 }131 132 133 134 void init()135 {136 cin >> n; ans = 0;137 head = new node, head->init();138 foe(i, 1, n)139 scanf("%s", str), build();140 141 build_ac();142 scanf("%s", str);143 }144 145 int main()146 {147 148 #ifndef ONLINE_JUDGE149 freopen("input.txt", "r", stdin);150 #endif151 152 int t; cin >> t;153 while(t--)154 {155 init();156 solve();157 printf("%d\n", ans);158 }159 160 return 0;161 }
View Code

 

转载于:https://www.cnblogs.com/chaoswr/p/9783281.html

你可能感兴趣的文章
(七十八)使用第三方框架INTULocationManager实现定位
查看>>
LeetCode问题:搜索插入位置
查看>>
JVM基础学习之基本概念、可见性与同步
查看>>
UML入门
查看>>
CodeForces - 524F And Yet Another Bracket Sequence
查看>>
python学习笔记-day10-2【多进程,多线程】
查看>>
MySQL安装后的初始优化
查看>>
PHP记录商品历史纪录
查看>>
类型转换 盲区
查看>>
Android Studio does not point to a valid jvm
查看>>
第5月第13天 node cnpm安装 babel
查看>>
QTC++监控USB插拔
查看>>
Java生成javadoc
查看>>
ZedGraph控件的使用--属性和例子代码
查看>>
文件管理
查看>>
webpack
查看>>
Atitit.swift 的新特性 以及与java的对比 改进方向attilax 总结
查看>>
Atitit 图像处理 平滑 也称 模糊, 归一化块滤波、高斯滤波、中值滤波、双边滤波)...
查看>>
Android Camera——拍照(转自http://vaero.blog.51cto.com/4350852/779942)
查看>>
Java Web项目移植
查看>>