题目:
题解:
假设S是长度较长的集合。
将T中的串哈希,用map记录每个哈希值出现了多少次。
然后枚举S串,在map中找可以拼接的T串的个数。
串S由abc->cab是O(1)的
不要那么多次取模。
代码:
#include <map>
#include <string>
#include <cstdio>
#include <cstring>
#include <iostream>
#define LL long long
using namespace std;
const int N=4000005;
const int base=131;
const LL mod=998244353;
string s[N],t[N];LL mi[N];
map<LL,int>mp;
LL ksm(LL a,LL k)
{
LL ans=1;
for (;k;k>>=1,a=a*a%mod)
if (k&1) ans=ans*a%mod;
return ans;
}
int main()
{
int ts,tt,n,m;
scanf("%d%d%d%d",&ts,&tt,&n,&m);
if (n<m)
{
swap(ts,tt);swap(n,m);
for (int i=1;i<=tt;i++) cin>>t[i];
for (int i=1;i<=ts;i++) cin>>s[i];
}
else
{
for (int i=1;i<=ts;i++) cin>>s[i];
for (int i=1;i<=tt;i++) cin>>t[i];
}
//t是短的
int len=(n+m)/2;
for (int i=1;i<=tt;i++)
{
LL hs=0;
for (int j=0;j<m;j++) hs=(hs*base%mod+t[i][j])%mod;
mp[hs]++;
}
mi[0]=1;for (int i=1;i<=len;i++) mi[i]=mi[i-1]*base%mod;
LL ans=0;
LL inv=ksm(base,mod-2);
for (int i=1;i<=ts;i++)
{
LL qz=0,now=0;
for (int j=len;j<n;j++) qz=(s[i][j]*mi[len*2-j-1]+qz)%mod;
for (int j=0;j<len;j++) now=(now*base%mod+s[i][j])%mod;
for (int j=0;j<len;j++)
{
ans+=mp[(now-qz+mod)%mod];
now=((now-s[i][len-j-1]+mod)*inv%mod+s[i][len-j-1]*mi[len-1])%mod;
}
}
printf("%lld",ans);
}