传送门:bzoj4084
题解
题面非常坑!!!
要求的是
Si+Tj
S
i
+
T
j
,但实际上任意
Tj+Si
T
j
+
S
i
也可以算。
AC的程序跑出的两组数据:
input:
1 1 2 6
ab
abcdcd
output:
1
(按题意应该是0)
input:
1 1 2 2
aa
aa
output:
2
(显然为1)
卒
好吧,说说错误的标算:
实际上很简单很暴力,
O(n2)
O
(
n
2
)
预处理出长度小的集合的每个字符串的哈希值存在
map
m
a
p
里(数据水到单哈希可以过),再枚举另一个集合里的字符串,由于其长度必然
≥len1+len22
≥
l
e
n
1
+
l
e
n
2
2
,所以可以确定出完整字符串,在
map
m
a
p
里加上答案即可。
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<map>
#define RI register
using namespace std;
typedef long long ll;
const int mod=958244353,hs=47,N=4e6+10;
string s[N],t[N];ll ans;
int n,m,la,lb,pw[N],f[N];
map<int,int>mp;
inline int dc(int x,int y){x-=y;return x<0?x+mod:x;}
inline int ad(int x,int y){x+=y;return x>=mod?x-mod:x;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
int main(){
RI int i,j,res,mid,upp,tp,len;
scanf("%d%d%d%d",&n,&m,&la,&lb);
len=la+lb;mid=len>>1;
pw[0]=1;for(i=1;i<=len;++i) pw[i]=mul(pw[i-1],hs);
if(la<lb){
for(i=1;i<=n;++i) cin>>t[i];
for(i=1;i<=m;++i) cin>>s[i];
swap(n,m);swap(la,lb);
}else{
for(i=1;i<=n;++i) cin>>s[i];
for(i=1;i<=m;++i) cin>>t[i];
}
for(i=1;i<=m;++i){
for(res=0,j=0;j<lb;++j)
res=ad(1ll*res*hs%mod,t[i][j]-'a'+1);
mp[res]++;
}
upp=la-mid;
for(i=1;i<=n;++i){
for(j=1;j<=la;++j) f[j]=ad(1ll*f[j-1]*hs%mod,s[i][j-1]-'a'+1);
tp=dc(f[la],mul(f[la-upp],pw[upp]));
for(j=1;j+upp-1<=mid && j<=mid;++j){
res=dc(f[j+upp-1],mul(f[j-1],pw[upp]));
if(res==tp)
ans+=mp[ad(mul(dc(f[mid],mul(f[j+upp-1],pw[mid-j-upp+1])),pw[j-1]),f[j-1])];
}
for(;j<=mid;++j){
res=ad(mul(dc(f[mid],mul(f[j-1],pw[mid-j+1])),pw[upp-mid+j-1]),f[upp-mid+j-1]);
if(res==tp)
ans+=mp[dc(f[j-1],mul(f[upp-mid+j-1],pw[mid-upp]))];
}
}
printf("%lld\n",ans);
}