数一数(KMP+思维)
Posted MangataTS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数一数(KMP+思维)相关的知识,希望对你有一定的参考价值。
题目链接
https://ac.nowcoder.com/acm/contest/27589/B
题面
思路
我们思考能知道对于一个
f
(
s
,
t
)
f(s,t)
f(s,t) 只有
t
t
t 的长度小于等于
s
s
s 才能至少匹配成功,那么我们会发现我们只需要处理长度最小的字符串,因为其他字符串肯定会有一个
f
(
s
,
t
)
f(s,t)
f(s,t) 是为0的,因为长串不可能称为短串的子串,但是若只是对长度最小的字符串都对
n
n
n 个字符串求
k
m
p
kmp
kmp 匹配的话,也是会超时的,万一所有串的长度都一样呢,于是我们进一步观察能发现对于长度最短的字符串如果任意两两之间有一对不同,那么就会给累乘贡献一个
0
0
0 ,否则的话所有的短串的ans
值是一样的,我们只需要循环求一次kmp
即可,对于其他串我们直接输出
0
0
0 就好啦
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 998244353
#define endl "\\n"
#define PII pair<int,int>
#define INF 0x3f3f3f3f
const int N = 2e6+10;
int n;
struct KMP
int nextt[N];
void get_next(string &S)
int n = S.size(),i = 0,j = -1;
nextt[0] = -1;
while(i < n)
if(j == -1 || S[i] == S[j])
nextt[++i] = ++j;
else
j = nextt[j];
//S是匹配串、T是模板串
int get_times(string &S,string &T)//在S中查找T出现了多少次
int cnt = 0,i = 0,j = 0;
int len1 = S.size();
int len2 = T.size();
while(i < len1)
if(j == -1 || S[i] == T[j])
i++,j++;
else
j = nextt[j];
if(j == len2)
j = nextt[j],cnt++;
return cnt;
kmp;
string ch[N];
int lench[N];
int main()
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n;
int min_len = INF;
for(int i = 1;i <= n; ++i)
cin>>ch[i];
lench[i] = ch[i].size();
min_len = min(lench[i],min_len);
vector<string> Vec;
for(int i = 1;i <= n; ++i)
if(lench[i] == min_len)
Vec.push_back(ch[i]);
bool fg = true;
int l = Vec.size();
for(int i = 0;i < l - 1; ++i)
if(Vec[i] != Vec[i + 1])
fg = false;
break;
if(fg)
kmp.get_next(Vec[0]);
ll ans = 1LL;
for(int i = 1;i <= n; ++i)
ans = ans * (ll)kmp.get_times(ch[i],Vec[0]) % mod;
for(int i = 1;i <= n; ++i)
if(lench[i] == min_len) cout<<ans<<endl;
else cout<<0<<endl;
else
for(int i = 1;i <= n; ++i)
cout<<0<<endl;
return 0;
/*
2
AA
AAA
2
0
*/
以上是关于数一数(KMP+思维)的主要内容,如果未能解决你的问题,请参考以下文章