• 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);
    }
    
  • 相关阅读:
    TJU ACMICPC 2009314
    TJU ACMICPC 2009313
    素数(Prime Number)
    Android学习系列(1)为App签名(为apk签名)
    Android学习系列(10)App列表之拖拽ListView(上)
    Android学习系列(6)App模块化及工程扩展
    Android学习系列(7)App消息通知机制
    Android学习系列(4)App自适应draw9patch不失真背景
    Android学习系列(9)App列表之分组ListView
    Android技术积累:图片缓存管理
  • 原文地址:https://www.cnblogs.com/ET2006/p/Codeforces-1483F.html
Copyright © 2020-2023  润新知