【洛谷 P2444】 [POI2000]病毒(AC自动机)
2024-10-20 20:51:30
这么多字符串,肯定是自动机啦。
先建出AC自动机,然后怎么表示一个安全代码没有病毒代码呢?
就是存在一条路径不经过有病毒代码段结尾的节点呗。
所以呢?有环啊!dfs一下救星了。
#include <cstdio>
#include <queue>
#include <cstring>
#include <cstdlib>
using namespace std;
struct Node{
int fail, next[2], num;
}AC[1000010];
int n, u, cnt;
queue <int> q;
int vis[1000010], mark[1000010];
char a[2000010];
void insert(){
int len = strlen(a + 1), w;
u = 0;
for(int i = 1; i <= len; ++i){
w = a[i] - '0';
if(!AC[u].next[w])
AC[u].next[w] = ++cnt;
u = AC[u].next[w];
}
AC[u].num = 1;
}
void BuildFail(){
u = 0;
for(int i = 0; i < 2; ++i)
if(AC[u].next[i])
q.push(AC[u].next[i]);
while(q.size()){
u = q.front(); q.pop();
AC[u].num |= AC[AC[u].fail].num;
for(int i = 0; i < 2; ++i)
if(AC[u].next[i]){
q.push(AC[u].next[i]);
AC[AC[u].next[i]].fail = AC[AC[u].fail].next[i];
}
else
AC[u].next[i] = AC[AC[u].fail].next[i];
}
}
void dfs(int x){
if(AC[x].num) return;
if(vis[x]){ printf("TAK\n"); exit(0); }
if(mark[x]) return;
vis[x] = mark[x] = 1;
for(int i = 0; i < 2; ++i)
if(AC[x].next[i])
dfs(AC[x].next[i]);
vis[x] = 0;
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; ++i){
scanf("%s", a + 1);
insert();
}
BuildFail();
dfs(0);
printf("NIE\n");
return 0;
}
最新文章
- Java中分割字符串
- MAVEN build ,GOAL plugin ,execution
- Mac上如何修改默认打开方式
- js获取网页屏幕可见区域高度
- CQRS架构如何实现高性能
- bootstrap 按钮 文本 浮动 隐藏
- peoplesoft function PSTREENODE 通过 deptid 获得部门树 一级部门 code
- SQL学习指南第四篇
- Windows Internals 笔记——字符和字符串处理
- Tomcat报错invalid LOC header
- Python中4位1进制数与float浮点数互相转换
- C++: typedef与template的配合使用;
- difference among String,StringBuilder,StringBuffer
- PreparedStatement用途
- git命令(9): 常见问题cover
- iOS-消除CocoaPods内容警告
- Entity Framework应用:使用Code First模式管理事务
- Google Web Designer打开白屏问题的解决方案
- SQL宽字节注入
- Paper Reading - Long-term Recurrent Convolutional Networks for Visual Recognition and Description ( CVPR 2015 )