解题报告:这道题好像是挺裸的kmp算法吧,我不太懂,之前学过hh,于是去回看了一遍y总的视频,可恶,然后明白了kmp的大致思路,如果暴力枚举字符串是否匹配的话挺难办的复杂度O(n^2),kmp的思路是预处理出来ne数组,ne数组的下标代表以它为结尾的,他的值代表的是最长前缀和后缀相等的部分,如果匹配不上把j更新成ne[j],注意一点就是如果匹配上了j也要更新成ne[j],用来方便下次匹配。
这题是群主发的,,,我一开始以为很难,以为要一个字符串字符串来做,但是后来发现原来只要用最短的字符串去匹配就好啦,因为如果不是最小的长度的话匹配值肯定是0,0乘以任何数都是0啊,这样只要处理最小的长度的kmp乘积就可以了,string下标从0开始要用另外一个模板,挺蛋疼的,我也没咋掌握,还好yxc发了两个版本的,%%%y总,然后这个模板ne[0]要变成1否则会死循环(你可以试试),因为j从-1开始的。
#include<iostream>
using namespace std;
const int N=1000010;
string s[N];
int ne[N*2];
const long long mod=998244353;
long long kmp(int t,int idx)
{
long long ans=0;
for(int i=0,j=-1;i<s[t].length();i++)
{
while(j>=0&&s[t][i]!=s[idx][j+1]) j=ne[j];
if(s[t][i]==s[idx][j+1]) {
//cout<<s[t][i]<<' '<<s[idx][j+1]<<endl;
j++;
}
//cout<<i<<' '<<j<<endl;
if(j==s[idx].length()-1)
{
ans++;
j=ne[j];
}
}
return ans;
// cout<<ans<<endl;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
cin>>s[i];
int minv=1e9;
int idx;
for(int i=0;i<n;i++)
{
if(s[i].length()<minv)
{
minv=s[i].length();
idx=i;
}
}
ne[0]=-1;
string p=s[idx];
for(int i=1,j=-1;i<p.length();i++)
{
while(j>=0&&s[idx][i]!=s[idx][j+1]) j=ne[j];
if(s[idx][i]==s[idx][j+1]) j++;
ne[i]=j;
}
// cout<<idx<<endl;
long long res=1;
for(int j=0;j<n;j++)
{
res=res%mod*kmp(j,idx)%mod;
if(res==0)
break;
}
for(int i=0;i<n;i++)
{
if(s[i].length()>s[idx].length())
printf("0\n");
else
{
printf("%lld\n",res);
}
}
return 0;
}