[TJOI2017]DNA

这道题充分考验了选手的暴力水平。
我们算出\(lcp\)后一位一位暴力往后移。
甚至算\(lcp\)的时候都不需要什么非常高级的算法,直接用字符串哈希+二分判断就结束了。
代码:


#include <bits/stdc++.h>
#define il inline
#define gc getchar
const int MAXN = 1e5 + 10;
const int base = 163;
typedef unsigned long long ull;
using namespace std;
ull p[MAXN],h1[MAXN],h2[MAXN];
int n,m,i,j,k,T,ans,l1,l2;
char s1[MAXN],s2[MAXN];
il void print(int x) {
    if(x < 0) putchar('-'),x = -x;if(!x) {putchar('0');return;}
    static int Sta[20];Sta[0] = 0;
    while(x) Sta[++Sta[0]] = x % 10,x /= 10;
    for(int i = Sta[0];i >= 1;i--) putchar(Sta[i] + 48);
    return;
}
il ull get1(int l,int r) {
    return h1[r] - p[r - l + 1] * h1[l - 1];
}
il ull get2(int l,int r) {
    return h2[r] - p[r - l + 1] * h2[l - 1];
}
il int lcp(int S1,int S2,int len) {
    int l = 1,r = len,res = 0;
    while(l <= r) {
        int mid = l + r >> 1;
        if(get1(S1,S1 + mid - 1) == get2(S2,S2 + mid - 1)) {
            res = mid;l = mid + 1;
        } else r = mid - 1;
        //cout << l << ' ' << r << endl;
    }
    return res;
}
il bool judge(int x) {
    bool res = 0;int y = 1,len = x + l2 - 1,dbg = x;
    for(int i = 1;i <= 3;i++) {
        int tmp = lcp(x,y,l2 - y + 1);
        x += tmp + 1;y += tmp + 1;
        if(y > l2) return 1;
    } 
    return get1(x,len) == get2(y,l2);
}
int main() {
    scanf("%d",&T);
    while(T--) {
        scanf("%s",s1 + 1);
        scanf("%s",s2 + 1);
        l1 = strlen(s1 + 1),l2 = strlen(s2 + 1),ans = 0;   
        p[0]  = 1;for(int i = 1;i <= l1;i++) p[i] = p[i - 1] * base;
        h1[0] = 0;for(int i = 1;i <= l1;i++) h1[i] = h1[i - 1] * base + (s1[i] - 48);
        h2[0] = 0;for(int i = 1;i <= l2;i++) h2[i] = h2[i - 1] * base + (s2[i] - 48);
        for(int i = 1;i + l2 - 1 <= l1;i++) {
            if(judge(i)) ans++;   
        }
    //  lcp(2,2,4);
        print(ans);puts("");
    }   
}

转载于:https://www.cnblogs.com/Sai0511/p/10410217.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值