[TJOI2017]DNA

因为洛谷题目蛋疼BZOJ又关了就不贴题面了

等bzoj好了之后再贴题面

 

把两个接在一起暴力枚举原串中起始位置,比较时利用$height$贪心往后比对就好了

RMQ应该用ST表会快很多

但我快两年没碰oi了,细节不想推就敲了个线段树

差点被卡常

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 100010 * 2, INF = 1 << 30;
int n, m;
char s[maxn];
int sa[maxn], rank[maxn], height[maxn];
int tax[maxn], tp[maxn];
inline void tsort(){
    for(int i = 1; i <= m; i++) tax[i] = 0;
    for(int i = 1; i <= n; i++) tax[rank[i]]++;
    for(int i = 2; i <= m; i++) tax[i] += tax[i - 1];
    for(int i = n; i; i--) sa[tax[rank[tp[i]]]--] = tp[i];
}
inline bool cmp(int *arr, int l, int r, int k){
    return arr[l] == arr[r] && arr[l + k] == arr[r + k];
}
void suffix_sort(){
    m = 128;
    for(int i = 1; i <= n; i++) tp[i] = i;
    for(int i = 1; i <= n; i++) rank[i] = s[i];
    tsort();
    for(int k = 1, p = 0; p < n; k <<= 1, m = p){
        p = k;
        for(int i = 1; i <= k; i++) tp[i] = n - k + i;
        for(int i = 1; i <= n; i++) if(sa[i] > k) tp[++p] = sa[i] - k;
        tsort();
        swap(rank, tp);
        p = rank[sa[1]] = 1;
        for(int i = 2; i <= n; i++)
            rank[sa[i]] = cmp(tp, sa[i - 1], sa[i], k) ? p : ++p;
    }
    for(int i = 1, j, k = 0; i <= n; height[rank[i++]] = k)
        for(k ? k-- : 0, j = sa[rank[i] - 1]; s[i + k] == s[j + k]; k++);
}
int mi[maxn << 2];
void build(int l, int r, int x){
    if(l == r){
        mi[x] = height[l];
        return;
    }
    int mid = l + r >> 1;
    build(l, mid, x << 1);
    build(mid + 1, r, x << 1 | 1);
    mi[x] = min(mi[x << 1], mi[x << 1 | 1]);
}
int query(const int &ql, const int &qr, int l, int r, int x){
    if(ql <= l && r <= qr) return mi[x];
    int ret = INF, mid = l + r >> 1;
    if(ql <= mid) ret = min(ret, query(ql, qr, l, mid, x << 1));
    if(qr > mid) ret = min(ret, query(ql, qr, mid + 1, r, x << 1 | 1));
    return ret; 
}
inline bool judge(int f, int t, int len){
    int x, y, z, sum = 0;
    for(int i = 1; i <= 3; i++){
        x = rank[f];
        y = rank[t];
        if(x > y) swap(x, y);
        z = query(x + 1, y, 1, n, 1);
        f += z + 1;
        t += z + 1;
        sum += z + 1;
        if(sum >= len) return true;
    }
    x = rank[f];
    y = rank[t];
    if(x > y) swap(x, y);
    z = query(x + 1, y, 1, n, 1);
    f += z;
    t += z;
    sum += z;
    return sum >= len;
}
inline void work(int len1, int len2){
    int t1, t2, ans = 0;
    for(int i = 1, j = len1 + 1; i <= len1 - len2 + 1; i++)
        ans += judge(i, j, len2);
    printf("%d\n", ans);
}
int main(){
    int tttt;
    scanf("%d", &tttt);
    while(tttt--){
        int len1, len2;
        scanf("%s", s + 1);
        len1 = strlen(s + 1);
        scanf("%s", s + len1 + 1);
        len2 = strlen(s + len1 + 1);
        n = len1 + len2;
        suffix_sort();
        build(1, n, 1);
        work(len1, len2);
    }
    return 0;
}

 

posted @ 2019-09-24 22:25  jzyy  阅读(133)  评论(0编辑  收藏  举报