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