zoukankan      html  css  js  c++  java
  • CF1202E You Are Given Some Strings...

    给出一个字符串t和n个字符串

    设f(t,s)为s在t中的出现次数。

    (sum_{i=1}^nsum_{j=1}^nf(t,s_i+s_j))

    枚举划分点。

    对t的每个划分点x,处理出有多少个字符串是当前t[0,x]的后缀。

    然后反着建AC自动机,反着枚举划分点x,处理出有多少个字符串是当前t[x,n]的后缀。

    处理有多少个字符串是当前位置的前缀:建出fail树,求出根节点到当前位置的路径?

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=2e5+100;
    int n,tr[maxn][26],fail[maxn],tot;
    vector<int> g[maxn];
    int cnt[maxn];
    string t,s[maxn];
    int pre[maxn],lst[maxn];
    void insert (string s) {
    	int u=0;
    	for (char i:s) {
    		if (!tr[u][i-'a']) tr[u][i-'a']=++tot;
    		u=tr[u][i-'a'];
    	}
    	cnt[u]++;
    }
    void build () {
    	queue<int> q;
    	for (int i=0;i<26;i++) {
    		if (tr[0][i]) {
    			q.push(tr[0][i]);
    		}
    	}
    	while (q.size()) {
    		int u=q.front();
    		q.pop();
    		for (int i=0;i<26;i++) {
    			if (tr[u][i]) {
    				fail[tr[u][i]]=tr[fail[u]][i];
    				q.push(tr[u][i]);
    			}
    			else {
    				tr[u][i]=tr[fail[u]][i];
    			}
    		}
    	}
    }
    void dfs (int u,int f) {
    	cnt[u]+=cnt[f];
    	for (int v:g[u]) {
    		if (v==f) continue;
    		dfs(v,u);
    	}
    }
    int main () {
    	ios::sync_with_stdio(false);
    	cin>>t;
    	cin>>n;
    	for (int i=1;i<=n;i++) {
    		cin>>s[i];
    		insert(s[i]);
    	}
    	build();
    	for (int i=1;i<=tot;i++) {
    		g[i].push_back(fail[i]);
    		g[fail[i]].push_back(i);
    	}
    	dfs(0,0);
    	int u=0;
    	for (int i=0;i<t.size();i++) {
    		u=tr[u][t[i]-'a'];
    		pre[i]=cnt[u];
    	}
    	
    	for (int i=0;i<=tot;i++) for (int j=0;j<26;j++) tr[i][j]=0;
    	for (int i=0;i<=tot;i++) cnt[i]=fail[i]=0,g[i].clear();
    	tot=0;
    	for (int i=1;i<=n;i++) reverse(s[i].begin(),s[i].end());
    	for (int i=1;i<=n;i++) {
    		insert(s[i]);
    	}
    	build();
    	for (int i=1;i<=tot;i++) {
    		g[i].push_back(fail[i]);
    		g[fail[i]].push_back(i);
    	}
    	dfs(0,0);
    	u=0;
    	for (int i=t.size()-1;i>=0;i--) {
    		u=tr[u][t[i]-'a'];
    		lst[i]=cnt[u];
    	}
    	long long ans=0;
    	for (int i=0;i<t.size()-1;i++) {
    		ans+=1ll*pre[i]*lst[i+1];
    	}
    	printf("%lld
    ",ans);
    } 
    
  • 相关阅读:
    ES6特性
    使用mybatis插件拦截SQL
    前端下载文件的几种方式
    Electron-vue项目使用 Inno Setup 创建安装包
    Windows powershell 常用代码段
    Java8之Predicate, Consumer,Function基础使用
    Java8之Predicate接口使用
    使用Replica Set副本集方式搭建mongodb副本集群
    Typora的一些偏好设置
    使用Typora编写md文档并优雅地上传到博客园
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/15005925.html
Copyright © 2011-2022 走看看