Wannafly挑战赛9 B、数一数

题目链接:https://www.nowcoder.com/acm/contest/71/B

题目: 有n个字符串,问每个字符串在所有字符串中出现的次数的乘积;

flag:KMP

*可以容易得到结论:

         ①  长度不为最短的字符串b的乘积结果均为0,显然b在最短的字符串a中绝对不会出现,即为0,乘以任何还是0;

         ②  长度都等于最短的字符串的长度的字符串a、b乘积结果均相等,如果a与b不相同,则乘积绝对是0,a在b中出现的

              次数为0,b在a出现的次数为0;a与b全相同时,显然结果也相同;

*所以我们可以取任意一个最短的字符串与所有字符串(文本串)进行KMP匹配算法;

 时间复杂度O(len(最短字符串长度)+len(所有字符串总长度));

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <string.h>
#define Mod  998244353
#define llt long long
using namespace std;

const int Size=1e6+10;
string s[Size];
int Next[2*Size];

void getNext(int x){
    Next[0]=-1;
    Next[1]=0;
    int j=0;
    for(int i=2;i<=s[x].length();++i){
        while(j!=-1&&s[x][j]!=s[x][i-1])j=Next[j];
        Next[i]=++j;
    }
}

llt KMP(int x,int y){
    llt ans=0;
    int len=0;
    for(int i=0;i<s[x].length();++i){
        while(len==s[y].length()||(len!=-1&&s[x][i]!=s[y][len]))len=Next[len];
        ++len;
        if(len==s[y].length())++ans;
    }
    return ans;
}
int main(){
    int n;scanf("%d",&n);
    int Mixn=2*1e7,idx=0;
    for(int i=1;i<=n;++i){
        cin>>s[i];
        if(Mixn>s[i].length()){Mixn=s[i].length();idx=i;}
    }
    llt ans=1;
    getNext(idx);
    for(int i=1;i<=n;++i)
        ans=ans*KMP(i,idx)%Mod;
    for(int i=1;i<=n;++i)
      if(s[i].length()==s[idx].length())printf("%lld\n",ans);
      else printf("0\n");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值