博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU 2222 Keywords Search(ac自动机模板)
阅读量:6232 次
发布时间:2019-06-21

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

Problem Description
In the modern time, Search engine came into the life of everybody like Google, Baidu, etc.
Wiskey also wants to bring this feature to his image retrieval system.
Every image have a long description, when users type some keywords to find the image, the system will match the keywords with description of image and show the image which the most keywords be matched.
To simplify the problem, giving you a description of image, and some keywords, you should tell me how many keywords will be match.
 

 

Input
First line will contain one integer means how many cases will follow by.
Each case will contain two integers N means the number of keywords and N keywords follow. (N <= 10000)
Each keyword will only contains characters 'a'-'z', and the length will be not longer than 50.
The last line is the description, and the length will be not longer than 1000000.
 

 

Output
Print how many keywords are contained in the description.
 

 

Sample Input
1
5
she
he
say
shr
her
yasherhs
 

 

Sample Output
3

 以前总以为字符串很难学就一直没认真去学,遇见字符串的题,大部分都果断放弃了,哇现在看来真的是后悔。只要认真,学的还是挺快的

思路:ac自动机的模板题啦,找了很多大神的博客讲解ac自动机,终于算是弄懂一点点了吧,还是直接附上代码吧,都是套模板的题

 

1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 using namespace std; 8 struct node { 9 int data;10 node *fail;11 node *next[26];12 node() {13 data = 0; fail = NULL;14 memset(next, 0, sizeof(next));15 }16 };17 node* Insert(node *root, string str)18 {19 node *p = root;20 int len = str.length();21 for (int i = 0; str[i]; i++) {22 int x = str[i] - 'a';23 if (p->next[x] == NULL)24 p->next[x] = new node;25 p = p->next[x];26 }27 p->data++;28 return root;29 }30 void build_ac(node *root)31 {32 node *p, *tmp;33 queue
Q;34 Q.push(root);35 while (!Q.empty()){36 p = Q.front(); Q.pop();37 for (int i = 0; i < 26; i++) {38 if (p->next[i] != NULL) {39 if (p == root)40 p->next[i]->fail = root;41 else {42 tmp = p->fail;43 while (tmp) {44 if (tmp->next[i]) {45 p->next[i]->fail = tmp->next[i];46 break;47 }48 tmp = tmp->fail;49 }50 if (tmp == NULL)p->next[i]->fail = root;51 }52 Q.push(p->next[i]);53 }54 }55 }56 }57 int ac(node *root, string str)58 {59 int ans = 0, len = str.length();60 node *p = root, *tmp;61 for (int i = 0; i < len; i++) {62 while (p->next[str[i] - 'a'] == NULL && p != root)p = p->fail;63 p = p->next[str[i] - 'a'];64 if (p == NULL)p = root;65 tmp = p;66 while (tmp != root && tmp->data != -1) {67 ans += tmp->data;68 tmp->data = -1;69 tmp = tmp->fail;70 }71 }72 return ans;73 }74 int main()75 {76 ios::sync_with_stdio(false);77 int t, n;78 cin >> t;79 while (t--) {80 cin >> n;81 string s; node *root = new node;82 for (int i = 0; i < n; i++) {83 cin >> s;84 Insert(root, s);85 }86 build_ac(root);87 cin >> s;88 cout << ac(root, s) << endl;89 }90 return 0;91 }
链表

有时候对空间要求比较高的时候用链表会爆空间,可能就需要使用静态数组来代替指针,也可以根据题目要求来限制插入字典树的单词个数来降低空间复杂度例如

1 #include
2 #include
3 #include
4 #include
5 #include
6 7 using namespace std; 8 const int maxn = 1000010; 9 const int max_tot = 500010;10 const int max_size = 26;11 char s[maxn], t[100];12 struct AC {13 int trie[max_tot][max_size];14 int val[max_tot];15 int fail[max_tot], last[max_tot];16 int size;17 void Clear()18 {19 memset(trie[0], 0, sizeof(trie[0]));20 size = 1;21 }22 int idx(char x) { return x - 'a'; }23 void insert(char *str) {24 int k = 0;25 for (int i = 0; str[i]; i++) {26 int x = idx(str[i]);27 if (!trie[k][x]) {28 memset(trie[size], 0, sizeof(trie[size]));29 val[size] = 0;30 trie[k][x] = size++;31 }32 k = trie[k][x];33 }34 val[k]++;35 }36 void GetFail()37 {38 queue
Q;39 fail[0] = 0; int k = 0;40 for (int i = 0; i < max_size; i++) { //计算第一层的fail指针跟last指针41 k = trie[0][i];42 if (k) {43 Q.push(k);44 fail[k] = 0;45 last[k] = 0;46 }47 }48 while (!Q.empty()) {49 int r = Q.front(); Q.pop();50 for (int i = 0; i < max_size; i++) {51 k = trie[r][i];52 if (!k) {53 trie[r][i] = trie[fail[r]][i];54 continue;55 }56 Q.push(k);57 int v = fail[r];58 while (v && !trie[v][i])v = fail[k];59 fail[k] = trie[v][i];60 last[k] = (val[fail[k]] ? fail[k] : last[fail[k]]);61 }62 }63 }64 int Find(char *str) {65 int k = 0, cnt = 0;66 for (int i = 0; str[i]; i++) {67 int x = idx(str[i]);68 k = trie[k][x];69 int tmp = 0;70 if (val[k])tmp = k;71 else if (last[k])tmp = last[k];72 while (tmp) {73 cnt += val[tmp];74 val[tmp] = 0;75 tmp = last[tmp];76 }77 }78 return cnt;79 }80 }ac;81 int main()82 {83 ios::sync_with_stdio(false);84 int t, n;85 cin >> t;86 while (t--) {87 cin >> n;88 ac.Clear();89 for (int i = 1; i <= n; i++) {90 cin >> s;91 ac.insert(s);92 }93 ac.GetFail();94 cin >> s;95 cout << ac.Find(s) << endl;96 }97 return 0;98 }
静态数组

 

转载于:https://www.cnblogs.com/wangrunhu/p/9544900.html

你可能感兴趣的文章
首都机场以后也能刷脸坐飞机了
查看>>
PyQt的Layout的比例化分块。
查看>>
python os模块
查看>>
随机生成验证码
查看>>
用Windows画图改变图片大小(附Linux企鹅头像完全版)。
查看>>
NOSQL系列-Redis精简版安装与Ruby测试
查看>>
追MM 之适配器模式实现
查看>>
一种测试方向的探讨-基于模型测试调研引发的思考 - 2
查看>>
Windows 7可以拯救微软Netbook市场
查看>>
彻底清除 mplay.com与mplay.exe病毒
查看>>
向右键添加新建脚本菜单
查看>>
Office 2010带来的协同工作体验
查看>>
MySQL 常见错误提示
查看>>
Dynamips ADSL实验之一pppoeoa(工大瑞普修正版)
查看>>
SQL Server 2012 Always on Availability Groups安装Step by step 1
查看>>
磁盘及文件操作命令
查看>>
shell 学习之case语句
查看>>
体验async/await异步编程
查看>>
Mac OS Mavericks “本地项目”钥匙串
查看>>
用winhex给自己的文件加把锁
查看>>