[BZOJ2938][POI2000]病毒(AC自动机+dfs)
2018-03-12 14:39
531 查看
题目:
我是超链接题解:
简单的来说,就是构造一个只含0和1的字符串,不能与Trie完成匹配(即包含病毒代码)。我们采用深搜的方式,往构造的字符串中添0或1。对于每个位置now,vis表示这个位置往后能不能添加成功,如果成功就立刻返回,不成功就继续找路,怎么都不能成功只能返回0了要注意is_end节点的传递性,即如果fail是end,这个节点也要是end,否则会WA。
代码:
#include <cstdio> #include <queue> #include <cstring> using namespace std; const int N=30005; bool is_end ;int ch [30],cnt,fail ,vis ;char st ; void insert() { int now=0,l=strlen(st); for (int i=0;i<l;i++) { int x=st[i]-'0'; if (!ch[now][x]) ch[now][x]=++cnt; now=ch[now][x]; } is_end[now]=1; } void sp() { queue <int> q; if (ch[0][0]) q.push(ch[0][0]); if (ch[0][1]) q.push(ch[0][1]); while (!q.empty()) { int now=q.front(); q.pop(); for (int i=0;i<=1;i++) { if (!ch[now][i]) { ch[now][i]=ch[fail[now]][i]; continue; } fail[ch[now][i]]=ch[fail[now]][i]; if (is_end[fail[ch[now][i]]]) is_end[ch[now][i]]=1; q.push(ch[now][i]); } } } bool dfs(int now) { if (vis[now]!=-1) return vis[now]; vis[now]=1;int noww=now; for (int i=0;i<=1;i++) { now=noww; while (now && !ch[now][i]) now=fail[now]; now=ch[now][i]; if (is_end[now]) continue; if (dfs(now)) {vis[noww]=1;return 1;} } vis[noww]=0;return 0; } int main() { memset(vis,-1,sizeof(vis)); int n;scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%s",&st),insert();sp(); if (dfs(0)) printf("TAK");else printf("NIE"); }
相关文章推荐
- bzoj2938 [Poi2000]病毒(AC自动机+DFS找环)
- bzoj2938 [Poi2000]病毒
- [bzoj2938][Poi2000]病毒 AC自动机
- bzoj 2938 [Poi2000]病毒
- bzoj2938 [Poi2000]病毒
- bzoj2938 [POI2000]病毒(ACAM+拓扑序判环)
- BZOJ 2938 [Poi2000]病毒(AC自动机)
- 【bzoj2938】[Poi2000]病毒 trie图+dfs
- [BZOJ2938][Poi2000]病毒(AC自动机+拓扑排序)
- [BZOJ 2938][Poi2000]病毒
- [bzoj2938][Poi2000]病毒
- 【bzoj2938】[Poi2000]病毒
- BZOJ 2938 Poi2000 病毒 AC自动机+拓扑排序
- 【bzoj2938】[Poi2000]病毒 AC自动机
- Hnu 10104 病毒 (AC自动机+dfs)
- [BZOJ2938][POI2000]病毒 做题笔记
- bzoj2938 [Poi2000]病毒 ac自动机
- 【BZOJ2938】[Poi2000]病毒 AC自动机+DFS
- 【BZOJ2938】病毒(POI2000)-AC自动机+DFS判环
- BZOJ 2938 [Poi2000]病毒