HDU 4125 Moles 树状数组 + KMP

来源:互联网 发布:药智数据库会员 编辑:程序博客网 时间:2024/05/19 11:45

这题的重点就在于建树, 题目读懂以后, 就会发现, 树建好以后就是一颗排序二叉树。

于是每次用树状数组二分找该节点的插入点。

树建完以后DFS得到字符串, 由于节点非常多, 于是要手写栈。

字符串得到以后就是水水的KMP直接求匹配数了。

#include <cstdio>#include <cstring>#include <stack>using namespace std;const int N = 600007;const int M = 7007;int ch[N][2], root;int num[N];int ma, mi;int n, l1, l2;char s1[N << 1], s2[M];int next[M];inline int lb(int x){return x & (-x);}void add(int x){while(x <= n){num[x]++;x += lb(x);}}int que(int x){int ans = 0;while(x){ans += num[x];x -= lb(x);}return ans;}int bf(int l, int r, int a){int p = -1;while(l <= r){int m = (l + r) >> 1;if(p == m)break ;p = m;if(que(m) >= a)r = m;elsel = m;}return r;}void build(){int a;scanf("%d", &a);add(a);int b = que(a);if(root == 0){root = a;ma = mi = a;return ;}if(a < mi){ch[mi][0] = a;mi = a;return ;}if(a > ma){ch[ma][1] = a;ma = a;return ;}int tmp = bf(mi, a - 1, b - 1);if(!ch[tmp][1]){ch[tmp][1] = a;return ;}tmp = bf(a + 1, ma, b + 1);ch[tmp][0] = a;}void dfs(){l1 = 0;stack<int> S;S.push(root);while(!S.empty()){int u = S.top();s1[l1++] = u % 2 + '0';if(!ch[u][0] && !ch[u][1])S.pop();else if(ch[u][0]){int v = ch[u][0];ch[u][0] = 0;S.push(v);}else if(ch[u][1]){int v = ch[u][1];ch[u][1] = 0;S.push(v);}}s1[l1] = 0;}void getnext(){int i = 0, j = -1;next[0] = -1;while(s2[i])if(j == -1  || s2[i] == s2[j])next[++i] = ++j;elsej = next[j];}int KMP(){int i = 0, j = 0, ans = 0;while(s1[i]){if(j == -1 || s2[j] == s1[i]){i++;j++;}elsej = next[j];if(j == l2){ans++;j = next[j];}}return ans;}int main(){//freopen("in.txt", "r", stdin);int T, C = 1;scanf("%d", &T);while(T--){scanf("%d", &n);memset(num, 0, sizeof(num));memset(ch, 0, sizeof(ch));root = 0;for(int i = 0; i < n; i++)build();dfs();scanf("%s", s2);l2 = strlen(s2);getnext();printf("Case #%d: %d\n", C++, KMP());}return 0;}



原创粉丝点击