Hint
100%:
length(S)<=2000;
length(A)<=2000;
length(B)<=2000;
30%:都少个0。
题解
我们可以预处理出所有$A$串和$B$串在$S$中的位置。
找到合法的串,我们可以去找前缀和后缀的位置,取出中间的部分用$hash$判重就好了。
1 #include<set> 2 #include<map> 3 #include<cmath> 4 #include<ctime> 5 #include<queue> 6 #include<stack> 7 #include<vector> 8 #include<cstdio> 9 #include<string> 10 #include<cstring> 11 #include<cstdlib> 12 #include<iostream> 13 #include<algorithm> 14 #define LL long long 15 using namespace std; 16 const LL N=2000; 17 const LL MOD=1e8+7; 18 19 LL Max(const LL &a,const LL &b) {return a>b ? a:b;} 20 LL Min(const LL &a,const LL &b) {return a<b ? a:b;} 21 22 char S[N+5],A[N+5],B[N+5]; 23 LL ls,la,lb; 24 bool vis[N+5]; 25 LL ans; 26 LL q[N+5],hash[N+5]; 27 bool pd[MOD+5]; 28 29 bool find_hash(LL x) 30 { 31 if (pd[x]) return false; 32 pd[x]=1; 33 return true; 34 } 35 36 int main() 37 { 38 S[0]=A[0]=B[0]=‘$‘; 39 scanf("%s%s%s",S+1,A+1,B+1); 40 ls=strlen(S)-1,la=strlen(A)-1,lb=strlen(B)-1; 41 q[0]=1; 42 for (LL i=1;i<=ls;i++) q[i]=(q[i-1]*31)%MOD; 43 for (LL i=1;i<=ls;i++) hash[i]=(hash[i-1]*31+S[i]-‘a‘+1)%MOD; 44 for (LL i=1;i<=ls;i++) if (S[i]==B[1]) 45 { 46 LL j; 47 for (j=2;j<=lb;j++) if (S[i+j-1]!=B[j]) break; 48 if (j>lb) vis[i]=1; 49 } 50 for (LL i=1;i<=ls;i++) if (S[i]==A[1]) 51 { 52 LL j; 53 for (j=2;j<=la;j++) if (S[i+j-1]!=A[j]) break; 54 if (j>la) 55 { 56 for (LL j=Max(i,la-lb+i);j<=ls;j++) if (vis[j]) 57 { 58 LL r=j+lb-1; 59 if (find_hash((hash[r]+MOD-hash[i-1]*q[r-i+1]%MOD)%MOD)) ans++; 60 } 61 } 62 } 63 printf("%lld\n",ans); 64 return 0; 65 }