• CF1202E You Are Given Some Strings...


    CF1202E You Are Given Some Strings...

    下午这紫题2400看半天不会然后去做了黑题2700.晚上又回来搞这题.

    What an easy problem!How stupid I am! 真的只有2400啊

    关键在于想到枚举分界点

    我们发现答案可以分为两部分统计:

    • (T_{1,cdots,i}) 后缀的模式串个数 (f_i)

    • (T_{i,cdots,len}) 前缀的模式串个数 (g_i)

    那么 (ans=sum f_{i-1} imes g_i)

    那两部分看着就很AC自动机, 但是我没学扎实,都想到这里了还写了1h

    第一部分

    首先,必然是让文本串沿着 (Trie) 图跑,因为那代表的是它前缀的状态.

    那么现在的任务是对于 (Trie) 图上的每个节点统计"有几个模式串是它的后缀"

    这时往往借助 (fail) 树来求解

    (cnt_i) 表示 (Trie) 树上,以那个节点为终止节点的模式串数量

    考虑在 (fail) 树上通过一次下放得出每个节点的 (cnt_i) ,即对于每一个节点求出求出"有几个模式串是它的后缀"

    由于在 (fail) 树上,父节点是子节点的后缀,那么子节点的 (cnt) 应该加上父节点的 (cnt)

    所以下放一次就完事了

    第二部分

    把所有模式串翻转一下,倒着扫文本串让它在 (Trie) 图上跑求 (g_i) 即可

    如果能理解第一部分第二部分应该是显然的.

    但是注意:如果不翻转所有文本串也能过样例,然后 WA on test 6 可以被下面这组数据卡掉

    Input
    abcdabcd
    4
    d
    cd
    a
    ab
    Output
    6
    

    其实这个数据加上题目里两个样例结合起来用是非常强劲的数据,都过了基本上就能AC.很多时候只能过一个或两个,那就会WA

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef double db;
    #define x first
    #define y second
    #define sz(v) (int)v.size()
    #define pb(x) push_back(x)
    #define mkp(x,y) make_pair(x,y)
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=0;c=getchar();}
    	while(isdigit(c))x=x*10+c-'0',c=getchar();
    	return f?x:-x;
    }
    #define N 200005
    string T,str[N];
    int n,f[N],g[N];
    LL cnt[N];
    int ch[N][26],tot,fail[N];
    LL ans;
    vector<int>e[N];
    void clear(){
    	for(int i=0;i<=tot;++i)e[i].clear();
    	tot=0;
    	memset(cnt,0,sizeof(cnt));
    	memset(ch,0,sizeof(ch));
    	memset(fail,0,sizeof(fail));
    }
    void insert(string str){
    	int u=0;
    	for(int i=0;i<sz(str);++i){
    		int c=str[i]-'a';
    		if(!ch[u][c])ch[u][c]=++tot;
    		u=ch[u][c];
    	}
    	++cnt[u];
    }
    void build_fail(){
    	queue<int>q;
    	for(int i=0;i<26;++i)if(ch[0][i])q.push(ch[0][i]);
    	while(!q.empty()){
    		int u=q.front();q.pop();
    		for(int i=0;i<26;++i)
    			if(ch[u][i])fail[ch[u][i]]=ch[fail[u]][i],q.push(ch[u][i]);
    			else ch[u][i]=ch[fail[u]][i];
    	}
    	for(int i=1;i<=tot;++i)e[fail[i]].pb(i);
    }
    void dfs(int u){
    	for(int v:e[u])cnt[v]+=cnt[u],dfs(v);
    }
    signed main(){
    	ios::sync_with_stdio(0);
    	cin.tie(0),cout.tie(0);
    	cin>>T>>n;
    	for(int i=1;i<=n;++i)cin>>str[i];
    
    	for(int i=1;i<=n;++i)insert(str[i]);
    	build_fail(),dfs(0);
    	for(int u=0,i=0;i<sz(T);++i)u=ch[u][T[i]-'a'],f[i]=cnt[u];
    
    	clear();
    	for(int i=1;i<=n;++i)reverse(str[i].begin(),str[i].end()),insert(str[i]);
    	build_fail(),dfs(0);
    	for(int u=0,i=sz(T)-1;~i;--i)u=ch[u][T[i]-'a'],g[i]=cnt[u];
    
    	for(int i=1;i<sz(T);++i)ans+=1ll*f[i-1]*g[i];
    	cout<<ans<<'
    ';
    	return 0;
    }
    

    upd:我发现一个非常严重的问题,大概是因为我用了cin和string,是个人代码就跑得比我块>_<

  • 相关阅读:
    核心API的使用(给定一个字符串,统计每个字符出现的次数)
    将博客搬至CSDN
    [DEBUG] python写文件时print漏掉整行数据
    [DEBUG] pyinstaller打包-命令行报错 pyinstaller failed to execute script 脚本名
    [DEBUG] springboot结合freemaker和js实现页面跳转和传值-踩坑记录
    724. 寻找数组的中心索引
    1010. 总持续时间可被 60 整除的歌曲
    27.移除元素
    [tensorflow] 入门day1-数据整理与展示
    [tensorflow] 安装
  • 原文地址:https://www.cnblogs.com/zzctommy/p/13887219.html
Copyright © 2020-2023  润新知