题目链接:
分析:这题用hash来判重效率不错。可以先用KMP预处理出所有起点和终点,从每个起点出发,向后hash ,遇到终点就判断字符串是否出现过(若么出现过就ans+1),否则跳过。。
参考代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
const int maxn = 2050;
char T[maxn],Beg[maxn],End[maxn];
int fail[2][maxn] , pos[2][maxn];
int len0 , len1 ,lenT ,ans;
const int max_hash = 10000007;
const int B[2]={100007,999997};
struct HASH{
int flag[max_hash];
int record[max_hash];
void init(){
memset(flag,0,sizeof(flag));
memset(record,-1,sizeof(record));
}
void solve(){
ans = 0;
for(int i=0;i<lenT;i++) if(pos[0][i]) {
long long p=0 , q=0;
int M = i+max(len0,len1)-1;
for(int j=i;j<M;j++){
p=(p*B[0]+T[j]-'a'+1)%max_hash;
q=(q*B[1]+T[j]-'a'+1)%max_hash;
}
for(int j=M;j<lenT;j++){
p=(p*B[0]+T[j]-'a'+1)%max_hash;
q=(q*B[1]+T[j]-'a'+1)%max_hash;
if(pos[1][j-len1+1]){
int x = p;
while(flag[x] && record[x]!=q) x=(x+1)%max_hash;
if(!(flag[x] && record[x]==q)) {
ans++;
flag[x]=1 , record[x]=q;
}
}
}
}
}
};
HASH hs;
void get_fail(char *p,int *f){
int m = strlen(p);
f[0] = f[1] = 0;
int j=0;
for(int i=1;i<m;i++){
j = f[i];
while(j && p[j]!=p[i]) j = f[j];
f[i+1] = p[i]==p[j] ? j+1 : 0;
}
}
void kmp_match(char *T,char *p,int *f,int *pos){
memset(pos,0,sizeof(pos));
int n = lenT , m=strlen(p);
int j = 0;
for(int i=0;i<n;i++){
while(j && T[i]!=p[j]) j=f[j];
if(T[i]==p[j]) j++;
if(j==m) pos[i-m+1] = 1;
}
}
int main()
{
//hs.init();
scanf("%s%s%s",T,Beg,End);
len0 = strlen(Beg) , len1 = strlen(End) ,lenT = strlen(T);
get_fail(Beg,fail[0]) , get_fail(End,fail[1]);
kmp_match(T,Beg,fail[0],pos[0]);
kmp_match(T,End,fail[1],pos[1]);
hs.solve();
printf("%d\n",ans);
return 0;
}