Codeforces 1483F

Posted ET2006

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 1483F相关的知识,希望对你有一定的参考价值。

Codeforces 题目传送门 & 洛谷题目传送门

一道 ACAM 的 hot tea

首先建出 ACAM。考虑枚举长串,以及短串在长串中出现的最后位置 \\(j\\),这个复杂度显然是 \\(\\mathcal O(\\sum|s_i|)\\) 的不会出问题。那么显然只有以 \\(s_{i,j}\\) 为结尾的、长度最长的字符串才有可能被统计进答案,否则就不满足题目中的条件了,而这个字符串,显然就是 \\(s_{i,j}\\) 对应位置在 fail 树上向上跳得到的第一个是某个字符串结尾的位置所对应的字符串,这个可以通过对 fail 树进行一遍 DFS 求出。

其次,仔细想想就会发现这些字符串也并不是所有都真的符合条件,如果我们把这一个个字符串看作一个个框,那么如果一个框被另一个框完全包含,那显然也是不合法的,这个可以通过记录个啥数组然后线性扫一遍把这些不合法的排除掉。但是再即便是排除掉这些不合法的字符串之后也有可能出现不合法,或者同一字符串被重复统计的情况,因为对于一个未被排除掉的字符串 \\(s_i[l...r]\\),有可能存在它的另一个出现位置 \\(s_i[l\'...r\']\\),满足 \\(s_i[l\'...r\']\\) 不是以 \\(s_{i,r\'}\\) 结尾的长度最长的符合要求的字符串,或者是以 \\(s_{i,r\'}\\) 结尾的长度最长的符合要求的字符串但被另外一个框完全包含。怎么 check 这样的情况呢?好办,拿个 map 记录一下所有字符串在 \\(s_i\\) 中被统计的次数,然后在 map 里面扫描一遍看所有字符串 \\(s\'\\)\\(s_i\\) 中出现次数是否等于其被统计的次数,如果是则答案加 \\(1\\),否则说明 \\(s\'\\) 肯定有被排除掉的情况,就不能产生贡献了。

时间复杂度 \\(|S|\\log|S|\\)

const int MAXN=1e6; 
int n,ch[MAXN+5][28],ncnt=0,fail[MAXN+5],ed[MAXN+5],ps[MAXN+5];
string s[MAXN+5];
void insert(string s,int id){
	int cur=0;
	for(int i=0;i<s.size();i++){
		if(!ch[cur][s[i]-\'a\']) ch[cur][s[i]-\'a\']=++ncnt;
		cur=ch[cur][s[i]-\'a\'];
	} ed[id]=cur;ps[cur]=id;
}
int hd[MAXN+5],to[MAXN+5],nxt[MAXN+5],ec=0,bgt[MAXN+5],edt[MAXN+5],tim;
void adde(int u,int v){to[++ec]=v;nxt[ec]=hd[u];hd[u]=ec;}
void getfail(){
	queue<int> q;
	for(int i=0;i<26;i++) if(ch[0][i]) q.push(ch[0][i]);
	while(!q.empty()){
		int x=q.front();q.pop();
		for(int i=0;i<26;i++){
			if(ch[x][i]) fail[ch[x][i]]=ch[fail[x]][i],q.push(ch[x][i]);
			else ch[x][i]=ch[fail[x]][i];
		}
	}
	for(int i=1;i<=ncnt;i++) adde(fail[i],i);
}

以上是关于Codeforces 1483F的主要内容,如果未能解决你的问题,请参考以下文章

[Codeforces Round #522 (Div. 2, based on Technocup 2019 Elimination Round 3)][C. Playing Piano](代码片段

c_cpp Codeforces片段

Codeforces 86C Genetic engineering(AC自动机+DP)

CodeForces 1005D Polycarp and Div 3(思维贪心dp)

(Incomplete) Codeforces 394 (Div 2 only)

CodeForces 931F Teodor is not a liar!