• 洛谷P3763 [TJOI2017]DNA


     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <string>
     5 using namespace std;
     6 typedef unsigned long long ull; 
     7 const int N=100005,p=131;//p进制 hash 
     8 int T,n,ans,len1,len2;
     9 ull f[N],key1[N],key2[N];
    10 char s1[N],s2[N];
    11 void init(){//字符串hash 
    12     memset(key1,0,sizeof(key1));//可以通过对二分和判定答案时边界的控制避免每次memset的耗时 
    13     memset(key2,0,sizeof(key2));
    14     for(int i=1;i<=len1;++i){
    15         key1[i]=key1[i-1]*p+(ull)s1[i];
    16     }
    17     for(int i=1;i<=len2;++i){
    18         key2[i]=key2[i-1]*p+(ull)s2[i];
    19     }
    20 }
    21 ull query(int flag,int pos1,int pos2){//查询两个字符串中pos1到pos2的hash值 
    22     if(flag==1) return key1[pos2]-key1[pos1-1]*f[pos2-pos1+1];
    23     else return key2[pos2]-key2[pos1-1]*f[pos2-pos1+1];
    24 }
    25 int lcp(int pos1,int pos2){//二分+hash求s1串中以pos1位置开始和s2串中以pos2位置开始的lcp 
    26     int l=0,r=min(len1,len2);//r设的较大 貌似可以通过计算传入r 可以避免每次求hash值时memset的时间 
    27     while(l<r){
    28         int mid=(l+r+1)>>1;//丑陋的二分写法... 
    29         if(mid>0&&query(1,pos1,pos1+mid-1)==query(2,pos2,pos2+mid-1)) l=mid;
    30         else r=mid-1;
    31     }
    32     return l;
    33 }
    34 bool check(int pos){
    35     int cnt=0,pos2=1,t;
    36     while(cnt<3){//跳三次还不同说明三处以上不同 
    37         t=lcp(pos,pos2);//lcp 
    38         pos+=t+1;//这一位不同 两个指针跳到lcp后一位 
    39         pos2+=t+1;
    40         if(pos2>len2) return true;
    41         ++cnt;
    42     }
    43     t=lcp(pos,pos2);//最后判断一下 可能跳三次以后到达s2最后一位 恰巧相等 
    44     pos+=t,pos2+=t;
    45     return pos2>len2;
    46 }
    47 int main(){
    48     f[0]=1;
    49     for(int i=1;i<=N;++i) f[i]=f[i-1]*p;//预处理p的幂 减少计算耗时 
    50     scanf("%d",&T);
    51     while(T--){
    52         scanf("%s",s1+1);
    53         scanf("%s",s2+1);
    54         len1=strlen(s1+1),len2=strlen(s2+1);
    55         if(len1<len2) {//貌似不用解释了??? 
    56             puts("0");
    57             continue;
    58         }
    59         init();//hash 预处理 
    60         ans=0;
    61         for(int i=1;i<=len1-len2+1;++i)//枚举每一位作为起点 
    62             if(check(i)) ++ans;
    63         printf("%d
    ",ans);
    64     }
    65     return 0;
    66 }
  • 相关阅读:
    Discuz论坛自动发帖机
    C#测试数据库连接是否成功
    JS重写提示框(confirm)
    随笔 选择
    随笔 诚实
    web项目经理手册【1】版本控制流程
    Asp.net多层架构中的变量引用与传递
    ASP.NET跨页面传值技巧总结
    web项目经理手册【3】Code Review
    web项目经理手册【7】项目经理需要铭记在心的话
  • 原文地址:https://www.cnblogs.com/yu-xing/p/10352000.html
Copyright © 2020-2023  润新知