首页 > 其他分享 >【字符串】#2938. [Poi2000]病毒

【字符串】#2938. [Poi2000]病毒

时间:2022-08-31 18:33:17浏览次数:64  
标签:ch 2938 int tr Poi2000 dfs go 字符串 fail

分析

不难想到使用 Trie 图来模拟匹配的过程。

那么要求的就等价于:判断是否可以从 Trie 图的根节点 \(0\) 出发不经过非法节点找到一个环。

非法节点则等价于:插入的模式串在 Trie 中对应的叶子节点 \(t\)、满足 \(fail[u]=t\) 的所有节点 \(u\)。

最后使用一遍 \(\texttt{dfs}\) 在 Trie 图上找环即可。

实现

  • 在插入模式串以及建立 \(fail\) 指针时利用 \(fail\) 的关系标记非法节点。
  • \(\texttt{dfs}\) 找环就是维护一个访问数组 \(vis[]\) 以及是否在栈中的数组 \(ins[]\),然后当遇到一个点在 \(\texttt{dfs}\) 树对应的栈中的时候就返回 \(true\) 即可。
// Problem: P2444 [POI2000]病毒
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2444
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
 
#define debug(x) cerr << #x << ": " << (x) << endl
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
#define all(x) (x).begin(), (x).end()
 
#define x first
#define y second
using pii = pair<int, int>;
using ll = long long;
 
inline void read(int &x){
    int s=0; x=1;
    char ch=getchar();
    while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
    while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
    x*=s;
}

const int N=1e5+5;

int n;

int tr[N][2], idx;
int fail[N];
bool ng[N];

void insert(string &s){
	int u=0;
	for(auto &c: s){
		int val=c-'0';
		int &go=tr[u][val];
		if(!go) go=++idx;
		u=go;
	}
	ng[u]=true;
}

void build(){
	queue<int> q;
	rep(c,0,1) if(tr[0][c]){
		q.push(tr[0][c]);
		fail[tr[0][c]]=0;
	}
	
	while(q.size()){
		int u=q.front(); q.pop();
		rep(c,0,1){
			int &go=tr[u][c];
			if(!go) go=tr[fail[u]][c];
			else fail[go]=tr[fail[u]][c], ng[go]|=ng[fail[go]], q.push(go);
		}
	}
}

bool vis[N], ins[N];

bool dfs(int u){
	vis[u]=ins[u]=true;
	rep(c,0,1){
		int go=tr[u][c];
		if(ins[go]) return true;
		if(ng[go] || vis[go]) continue;
		if(dfs(go)) return true;
	}
	ins[u]=false;
	return false;
}

void solve(){
	puts(dfs(0)? "TAK": "NIE");
}

signed main(){
	cin>>n;
	rep(i,1,n){
		string s; cin>>s;
		insert(s);
	}	
	build();
	
	solve();
	
	return 0;
}

标签:ch,2938,int,tr,Poi2000,dfs,go,字符串,fail
From: https://www.cnblogs.com/Tenshi/p/16644151.html

相关文章

  • shell中字符串和引号("",''.``的区分)
    场景1:变量为字符串类型,引用变量时添加引号等的区分【概念】变量的引用主要包含四类:双引号引用、单引号引用、反引号引用、反斜线引用""双引号......
  • 字符串数据
    今天一个同事问为啥字符串要多定义一位,正好,我把原因和大家也说下:定义字符串数组的时候,长度要多一位,用于\0存放,作为字符串结束。如果没有\0,使用strstr、strlen等操作时会......
  • 1071. 字符串的最大公因子
    对于字符串 s和 t,只有在 s=t+...+t(t自身连接1次或多次)时,我们才认定 “t能除尽s”。给定两个字符串 str1 和 str2 。返回最长字符串 x,要求满足 x......
  • 基础数据类型之数字和字符串
    1.数字类型数字类型的数据可以相互的进行+-/*、也可以进行相互的比较(<>=)1.1整型intage=18记录年龄等整数print(type(age))#int类型int()方法可以将其他类型的数据转换......
  • 数值数组与字符串数组转换
    数值数组转字符串数组方法一:vararr1=[1,2,5];arr1=arr1.map(String);//将arr1转换为字符串数组console.log(arr1);//结果:["1","2","5"]方法二:vararr1=......
  • 使用java处理字符串公式运算的方法
    在改进一个关于合同的项目时,有个需求,就是由于合同中非数据项的计算公式会根据年份而进行变更,而之前是将公式硬编码到系统中的,只要时间一变,系统就没法使用了,因此要求合同中......
  • MySQL提取字符串中的数字
    1--方法12selectreplace(reverse(FORMAT(reverse('国械注准20173463309'),0)),',','');34--方法25CREATEFUNCTIONget_number(paramvarchar(50))......
  • 计算字符串最后一个单词的长度,单词以空格隔开
    计算字符串最后一个单词的长度,单词以空格隔开,字符串长度小于5000。(注:字符串末尾不以空格为结尾)如:输入hellonowcoder长度为8经典算法如下importjava.util.Scanner;pu......
  • C#替换字符串中第一个出现的指定字符串
    Regexr=newRegex(childstr);str=r.Replace(str,"",1);应用:已知一个字符串,比如asderwsde,寻找其中的一个子字符串比如sde的个数,如果没有返回0,有的话返回子字符串......
  • 字符串
    周期与Border的结构我们定义正整数\(p\)是串\(S\)的周期,当且仅当\(p\le|S|\)且\(\foralli\in[1,|S|-p],S_i=S_{i+p}\)。我们定义串\(T\)是串\(S\)的bor......