Description
允许至多三个位置不同的字符串匹配
枚举匹配起始位置,分治处理,用hash可以判定区间是否相等,若不相等则判断区间端点是否相等,找到至少4个不等的位置就return,否则递归到左右半部分处理
类似于线段树,时间复杂度O(nlogn)
#include<cstdio> #include<cstring> const int N=100007; typedef unsigned long long u64; const int p=1234577; int T,l1,l2,c; char s1[N],s2[N]; u64 h1[N],h2[N],pp[N]; void chk(int l1,int r1,int l2,int r2){ while(c<=3&&l1<=r1){ if(s1[l1]!=s2[l2])++l1,++l2,++c; else if(s1[r1]!=s2[r2])--r1,--r2,++c; else break; } if(c>3||l1>r1)return; if(h1[r1]-h2[r2]==(h1[l1-1]-h2[l2-1])*pp[r1-l1+1])return; int d=(r1-l1)>>1; chk(l1,l1+d,l2,l2+d); chk(l1+d+1,r1,l2+d+1,r2); } void work(){ l1=strlen(s1+1); l2=strlen(s2+1); for(int i=1;i<=l1;++i)h1[i]=h1[i-1]*p+s1[i]; for(int i=1;i<=l2;++i)h2[i]=h2[i-1]*p+s2[i]; int ans=0; for(int i=1;i<=l1-l2+1;++i){ c=0; chk(i,i+l2-1,1,l2); if(c<=3)++ans; } printf("%d\n",ans); } int main(){ for(int i=pp[0]=1;i<=100000;++i)pp[i]=pp[i-1]*p; for(scanf("%d",&T);T;--T){ scanf("%s%s",s1+1,s2+1); work(); } return 0; }