KMP
求子串的每个前缀在母串中出现的次数,然后反转再求一次,然后计算结果即可
PS:ZOJ评测好严格啊,不强制转换类型会WA。。。就因为这个WA了好久。。。一定不要偷懒啊!!!
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#define N 100050
using namespace std;
int jump[N],ans1[N],ans2[N];
char s1[N],s2[N],t1[N],t2[N];
void init(char *t)
{
jump[0]=-1;
int j=-1,len=strlen(t);
for(int i=1;i<len;i++)
{
while(j>-1&&t[i]!=t[j+1])j=jump[j];
if(t[i]==t[j+1])j++;
jump[i]=j;
}
}
void kmp(char *s,char *t)
{
int j=-1,len=strlen(s),len2=strlen(t);
for(int i=0;i<len;i++)
{
while(j>-1&&s[i]!=t[j+1])j=jump[j];
if(s[i]==t[j+1]){j++;ans1[j]++;}
//if(j==len2-1)
//{
// printf("%d\n",i-len2+1);
//}
}
}
void kmp2(char *s,char *t)
{
int j=-1,len=strlen(s),len2=strlen(t);
for(int i=0;i<len;i++)
{
while(j>-1&&s[i]!=t[j+1])j=jump[j];
if(s[i]==t[j+1]){j++;ans2[j]++;}
//if(j==len2-1)
//{
// printf("%d\n",i-len2+1);
//}
}
}
int main()
{
int tc,len1,len2;
long long ans;
scanf("%d",&tc);
getchar();
while(tc>0)
{
tc--;
memset(ans1,0,sizeof(ans1));
memset(ans2,0,sizeof(ans2));
gets(s1);
gets(s2);
len1=strlen(s1),len2=strlen(s2);
init(s2);
kmp(s1,s2);
for(int i=len2-1;i>=0;i--)if(jump[i]!=-1)ans1[jump[i]]+=ans1[i]; //这个要注意
t1[len1]='\0';t2[len2]='\0';
for(int i=len1-1;i>=0;i--)t1[len1-i-1]=s1[i];
for(int i=len2-1;i>=0;i--)t2[len2-i-1]=s2[i];
init(t2);
kmp2(t1,t2);
for(int i=len2-1;i>=0;i--)if(jump[i]!=-1)ans2[jump[i]]+=ans2[i]; //这个要注意
ans=0;
//for(int i=0;i<len2;i++)printf("%d\n",ans1[i]);
//cout<<endl;
//for(int i=0;i<len2;i++)printf("%d\n",ans2[i]);
for(int i=0;i<len2-1;i++)ans+=(long long)ans1[i]*(long long)ans2[len2-i-2]; //一定要强制类型转换啊,切记!!
printf("%lld\n",ans);
}
return 0;
}