ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

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;
}

 

posted on 2017-05-05 11:08  nul  阅读(248)  评论(0编辑  收藏  举报