欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

2020牛客暑期多校训练营(第二场)——A

程序员文章站 2022-04-02 18:51:02
...

All with Pairs

链接:https://ac.nowcoder.com/acm/contest/5667/A
来源:牛客网

时间限制:C/C++ 3秒,其他语言6秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
Given {n}n strings s_1, s_2, \cdots, s_ns
1

,s
2

,⋯,s
n

. Now define {f(s, t)}f(s,t) as the maximum {i}i that satisfy s_{1\dots i} = t_{|t|-i+1 \dots |t|}s
1…i

=t
∣t∣−i+1…∣t∣

, and if such {i}i doesn’t exist, {f(s, t) = 0}f(s,t)=0.
The Problem is to calculate:
\sum_{i=1}{n}\sum_{j=1}{n}f(s_i, s_j)^2 \pmod{998244353}∑
i=1
n


j=1
n

f(s
i

,s
j

)
2
(mod998244353)
输入描述:
The first line contains one integer n~(1 \leq n \leq 10^5)n (1≤n≤10
5
), denoting the number of given strings.
The following {n}n lines each contains a string s_i~(i = 1, 2, \cdots, n)s
i

(i=1,2,⋯,n).
It’s guaranteed that 1\leq |s_i|, \sum|s_i| \leq 10^61≤∣s
i

∣,∑∣s
i

∣≤10
6
and all strings only contain lowercase letters.
输出描述:
Only one line containing one integer, denoting the answer.
示例1
输入
复制
3
ab
ba
aba
输出
复制
29
题意:给定n个字符串,每一个串前缀和其他串的后缀进行匹配,计算匹配的最大长度的平方和。
题解:哈希函数预处理每一个字符串的后缀,并记录每一个哈希值,然后处理每个字符串的前缀哈希值,统计每个字符串的贡献值,但是,例如”aba“,这个字符,其前缀“a”,“aba”,会被重复统计,所以需要跑一遍kmp求出next数组,来处理掉这种重复的情况,最后计算答案即可。
由于哈希函数不经常写,忘记key值该怎么取了,wa了几次。
key应该是取较大的素数(我认为是这样)。

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const ll mod=998244353;
const int N=1e6+500;
const int key=131;
map<ull,int>mp;
string s[N];
int has[N];
int nex[N];
void Hash(string a) {
	ull cut=0;
	ull p=1;
	for(int i=a.size()-1; i>=0; --i) {
		cut+=p*(a[i]-'a'+1);
		p*=key;
		mp[cut]++;
	}
	return;
}
void kmp(string a,int n) {
	nex[0]=-1;
	int j=0,k=-1;
	while(j<n) {
		if(k==-1||a[k]==a[j])
			nex[++j]=++k;
		else k=nex[k];
	}
}
int main() {
	int n;
	scanf("%d",&n);
	for(int i=1; i<=n; ++i) {
		cin>>s[i];
		Hash(s[i]);
	}
	ll ans=0;
	for(int i=1; i<=n; ++i) {
		ull cut=0;
		int len=s[i].size();
		for(int j=0; j<len; ++j) {
			cut=cut*key+(s[i][j]-'a'+1);
			has[j+1]=mp[cut];
		}
		kmp(s[i],len);
		for(int j=1; j<=len; ++j) {
			has[nex[j]]-=has[j];
		}
		for(int j=1; j<=len; ++j) {
			ans=(ans+1ll*has[j]*j*j%mod)%mod;
		}
	}
	printf("%lld\n",ans);
	return 0;
}
相关标签: 字符串