ZROI2018普转提day6t3
分析
居然卡哈希数,万恶的出题人......
感觉我这个方法似乎比较呆,我的代码成功成为了全网最慢的代码qwq
应该是可以直接哈希的
但由于我哈希学的不好又想练练线段树维护哈希,于是就写了个线段树维护了一下哈希值
详见代码
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<unordered_map>
using namespace std;
#define uli unsigned long long
const long long HASH = 83;
const long long mod = 2181271;
long long pw[11000],d[11000];
long long len[11000],Ans;
char s[11000],t1[11000],t2[11000];
int is[mod+10];
inline void build(long long le,long long ri,long long wh,long long pl,long long k){
len[wh]=ri-le+1;
if(le==ri){
d[wh]=k%mod;
return;
}
long long mid=(le+ri)>>1;
if(mid>=pl)build(le,mid,wh<<1,pl,k);
else build(mid+1,ri,wh<<1|1,pl,k);
d[wh]=(d[wh<<1]+d[wh<<1|1]*pw[len[wh<<1]]%mod)%mod;
return;
}
struct node {
long long fi,se;
};
inline node q(long long le,long long ri,long long wh,long long x,long long y){
if(le>=x&&ri<=y)return node{d[wh]%mod,ri-le+1};
node Ans,a,b;
long long mid=(le+ri)>>1,cnt=0;
if(mid>=x)cnt+=1,a=q(le,mid,wh<<1,x,y);
if(mid<y)cnt+=2,b=q(mid+1,ri,wh<<1|1,x,y);
if(cnt==1)return a;
if(cnt==2)return b;
return node{(a.fi+b.fi*pw[a.se]%mod)%mod,a.se+b.se};
}
int main(){
long long n,m1,m2,i,j,k;
scanf("%s",s);
n=strlen(s);
pw[0]=1;
for(i=1;i<n;i++)pw[i]=pw[i-1]*HASH%mod;
long long h1=0,h2=0;
scanf("%s",t1);
m1=strlen(t1);
for(i=0;i<m1;i++)
h1=(h1+(t1[i]-'a')*pw[i]%mod)%mod;
scanf("%s",t2);
m2=strlen(t2);
for(i=0;i<m2;i++)
h2=(h2+(t2[i]-'a')*pw[i]%mod)%mod;
for(i=0;i<n;i++)
build(0,n-1,1,i,s[i]-'a');
memset(is,-1,sizeof(is));
for(i=max(m1,m2);i<=n;i++)
for(j=0;j+i-1<n;j++){
long long hsh=q(0,n-1,1,j,j+i-1).fi;
if(is[hsh]==i)continue;
if(q(0,n-1,1,j,j+m1-1).fi==h1&&
q(0,n-1,1,j+i-m2,j+i-1).fi==h2)Ans++;
is[hsh]=i;
}
cout<<Ans;
return 0;
}