题目链接: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;
}