CodeForces - 1202E You Are Given Some Strings...

题意:

给定一个字符串 t t t,以及 n n n 个字符串 s i s_i si,定义 f ( t , s ) f(t, s) f(t,s) 为 串 s s s 在串 t t t 中出现的次数, t + s t + s t+s 为字符串的拼接,求 ∑ i = 1 n ∑ i = 1 n f ( t , s i + s j ) \sum\limits_{i = 1}^{n}\sum\limits_{i = 1}^{n}f(t, s_i + s_j) i=1ni=1nf(t,si+sj) ( n , ∣ t ∣ , ∑ ∣ s i ∣ ≤ 2 × 1 0 5 ) (n, |t|, \sum |s_i| \leq 2×10^5) (n,t,si2×105)

链接:

https://codeforces.com/problemset/problem/1202/E

解题思路:

多模式串的匹配,可以考虑 A C AC AC 自动机。显然不能直接枚举模式串的拼接,那么反过来枚举主串 t t t 的匹配位置,在 A C AC AC 自动机上跑主串,每到一个结点,其 f a i l fail fail 父链上的模式串都可以在该位置和主串匹配,因此可以得到主串 t t t 以位置 i i i 结束的匹配数 g i g_i gi,再将所有字符串反向,再得到主串 t ′ t' t 以位置 i ′ i' i 结束的匹配数 g i ′ g'_i gi,那么枚举字符串拼接点的下标位置,对每个下标 i i i,贡献为 g i ′ ∗ g n − i ′ g_i' * g'_{n-i} gigni

参考代码:
#include<bits/stdc++.h>
 
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define sz(a) ((int)a.size())
#define pb push_back
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define gmid (l + r >> 1)
const int maxn = 2e5 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
 
char s[maxn], t[maxn];
int n, m;
 
struct AC{
 
	int nxt[maxn][26], fail[maxn], num[maxn], g[maxn];
	int cnt;
	int add(){
 
		++cnt; fail[cnt] = num[cnt] = 0; return cnt;
	}
	void init(){
 
		cnt = -1; add();
	}
	void insert(char *s){
 
		int p = 0;
		while(*s){
 
			int t = *s - 'a';
			if(!nxt[p][t]) nxt[p][t] = add();
			p = nxt[p][t];
			++s;
		}
		++num[p];
	}
	void cFail(){
 
		queue<int> q;
		for(int i = 0; i < 26; ++i) if(int v = nxt[0][i]) q.push(v);
		while(!q.empty()){
 
			int u = q.front(); q.pop();
			for(int i = 0; i < 26; ++i){
 
				if(int v = nxt[u][i]) fail[v] = nxt[fail[u]][i], num[v] += num[fail[v]], q.push(v);
				else nxt[u][i] = nxt[fail[u]][i];
			}
		}
	}
	void solve(){
 
		cFail();
		int p = 0;
		for(int i = 1; i <= n; ++i){
 
			p = nxt[p][t[i] - 'a'];
			g[i] = num[p];
		}
	}
} ac1, ac2;
 
int main() {
 
	ios::sync_with_stdio(0); cin.tie(0);
	cin >> t + 1;
	n = strlen(t + 1);
	cin >> m;
	ac1.init(), ac2.init();
	for(int i = 1; i <= m; ++i){
 
		cin >> s + 1;
		ac1.insert(s + 1);
		int tn = strlen(s + 1);
		reverse(s + 1, s + 1 + tn);
		ac2.insert(s + 1);
	}
	ac1.solve();
	reverse(t + 1, t + 1 + n);
	ac2.solve();
	ll ret = 0;
	for(int i = 1; i < n; ++i){
 
		ret += ac1.g[i] * 1ll * ac2.g[n - i];
	}
	cout << ret << endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的纺织品企业财务管理系统,源码+数据库+毕业论文+视频演示 在如今社会上,关于信息上面的处理,没有任何一个企业或者个人会忽视,如何让信息急速传递,并且归档储存查询,采用之的纸张记录模式已经不符合当使用要求了。所以,对纺织品企业财务信息管理的提升,也为了对纺织品企业财务信息进行更好的维护,纺织品企业财务管理系统的出现就变得水到渠成不可缺少。通过对纺织品企业财务管理系统的开发,不仅仅可以学以致用,让学到的知识变成成果出现,也强化了知识记忆,扩大了知识储备,是提升自我的一种很好的方法。通过具体的开发,对整个软件开发的过程熟练掌握,不论是期的设计,还是后续的编码测试,都有了很深刻的认知。 纺织品企业财务管理系统通过MySQL数据库与Spring Boot框架进行开发,纺织品企业财务管理系统能够实现对财务人员,员工,收费信息,支出信息,薪资信息,留言信息,报销信息等信息的管理。 通过纺织品企业财务管理系统对相关信息的处理,让信息处理变的更加的系统,更加的规范,这是一个必然的结果。已经处理好的信息,不管是用来查找,还是分析,在效率上都会成倍的提高,让计算机变得更加符合生产需要,变成人们不可缺少的一种信息处理工具,实现了绿色办公,节省社会资源,为环境保护也做了力所能及的贡献。 关键字:纺织品企业财务管理系统,薪资信息,报销信息;SpringBoot
CodeForces - 616D是一个关于找到一个序列最长的第k好子段的起始位置和结束位置的问题。给定一个长度为n的序列和一个整数k,需要找到一个子段,该子段不超过k个不同的数字。题目要求输出这个序列最长的第k好子段的起始位置和终止位置。 解决这个问题的方法有两种。第一种方法是使用尺取算法,通过维护一个滑动窗口来记录\[l,r\]不同数的个数。每次如果这个数小于k,就将r向右移动一位;如果已经大于k,则将l向右移动一位,直到个数不大于k。每次更新完r之后,判断r-l+1是否比已有答案更优来更新答案。这种方法的时间复杂度为O(n)。 第二种方法是使用枚举r和双指针的方法。通过维护一个最小的l,满足\[l,r\]最多只有k种数。使用一个map来判断数的种类。遍历序列,如果当数字在map不存在,则将种类数sum加一;如果sum大于k,则将l向右移动一位,直到sum不大于k。每次更新完r之后,判断i-l+1是否大于等于y-x+1来更新答案。这种方法的时间复杂度为O(n)。 以上是两种解决CodeForces - 616D问题的方法。具体的代码实现可以参考引用\[1\]和引用\[2\]的代码。 #### 引用[.reference_title] - *1* [CodeForces 616 D. Longest k-Good Segment(尺取)](https://blog.csdn.net/V5ZSQ/article/details/50750827)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Codeforces616 D. Longest k-Good Segment(双指针+map)](https://blog.csdn.net/weixin_44178736/article/details/114328999)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值