AC自动机 - 多模式串的匹配 --- HDU 3695 Computer Virus on Planet Pandora
Mean:
有n个模式串和一篇文章,统计有多少模式串在文章中出现(正反统计两次).
analyse:
好久没写AC自动机了,回顾一下AC自动机的知识。
本题在构造文章的时候需要仔细一点,其他没什么Trick,和普通AC自动机做法一样:
build Trie ---> build Fail_Ptr ---> matching_and_count
Time complexity: O(N*L+M)
Source code:
/* * this code is made by crazyacking * Verdict: Accepted * Submission Date: 2015-07-19-10.29 * Time: 0MS * Memory: 137KB */ #include <queue> #include <cstdio> #include <set> #include <string> #include <stack> #include <cmath> #include <climits> #include <map> #include <cstdlib> #include <iostream> #include <vector> #include <algorithm> #include <cstring> #define LL long long #define ULL unsigned long long using namespace std; const int M = 6000005; class node { public: bool flag; node *fail, *next[26]; node() { flag = false; fail = NULL; memset( next, NULL, sizeof next ); } }; node *root; queue<node*> q; char s[M], str[M]; void Insert( char *str ) { // build Trie-Tree node *p = root; int i = 0, index; while( str[i] ) { index = str[i] - 'A'; if( p->next[index] == NULL ) p->next[index] = new node(); p = p->next[index]; ++i; } p->flag = true; } void build_ac_automation( node *root ) { // build fail ptr root->fail = NULL; while( !q.empty() ) q.pop(); q.push( root ); while( !q.empty() ) { node *temp = q.front(); q.pop(); node *p = NULL; for( int i = 0; i < 26; ++i ) { if( temp->next[i] != NULL ) { if( temp == root ) temp->next[i]->fail = root; else { p = temp->fail; while( p != NULL ) { if( p->next[i] != NULL ) { temp->next[i]->fail = p->next[i]; break; } p = p->fail; } if( p == NULL ) temp->next[i]->fail = root; } q.push( temp->next[i] ); } } } } int query( node *root ) { // mathing and count node *p = root; int i = 0, ans = 0, index; while( str[i] ) { index = str[i] - 'A'; while( p->next[index] == NULL && p != root ) p = p->fail; p = p->next[index]; if( p == NULL ) p = root; node *temp = p; while( temp != root && temp->flag ) { ans++; temp->flag = false; temp = temp->fail; } i++; } return ans; } inline void build_str( char *s ) { int len = strlen( s ), cnt = -1; for( int i = 0; i < len; ++i ) { if( s[i] >= 'A' && s[i] <= 'Z' ) { str[++cnt] = s[i]; continue; } if( s[i] == '[' ) { ++i; int num = 0; for( ; s[i] >= '0' && s[i] <= '9'; ++i ) { num = num * 10 + ( s[i] - '0' ); } char ch = s[i]; ++i; for( int j = 1; j <= num; ++j ) str[++cnt] = ch; } } str[++cnt] = '\0'; } int main() { ios_base::sync_with_stdio( false ); cin.tie( 0 ); int Cas; scanf( "%d", &Cas ); while( Cas-- ) { root = new node(); int n; scanf( "%d", &n ); while( n-- ) { scanf( "%s", s ); Insert( s ); } build_ac_automation( root ); scanf( "%s", s ); build_str( s ); int ans = query( root ); strrev( str ); ans += query( root ); printf( "%d\n", ans ); } return 0; }
作者:北岛知寒
出处:https://www.cnblogs.com/crazyacking/p/4653984.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
2014-07-17 Trie数 --- 统计公共前缀