• Acwing-----算法基础课之第二讲(数据结构二)


    835 Trie字符串统计

    #include <iostream>
    using namespace std;
    
    const int N = 100010;
    int n;
    int son[N][26], cnt[N], idx; //下标是0的点既是根节点又是空结点
    char str[N];
    
    void insert(char str[]) {
        int p = 0;
        for (int i = 0; str[i]; ++i) {
            int u = str[i] - 'a';
            if (!son[p][u]) son[p][u] = ++idx;
            p = son[p][u];
        }
        cnt[p]++;
    }
    
    int query(char str[]) {
        int p = 0;
        for (int i = 0; str[i]; ++i) {
            int u = str[i] - 'a';
            if (!son[p][u]) return 0;
            p = son[p][u];
        }
        return cnt[p];
    }
    
    int main() {
        int n;
        cin >> n;
        while (n--) {
            char op[2];
            cin >> op >> str;
            if (op[0] == 'I') insert(str);
            else cout << query(str) << endl;
        }
        return 0;
    }
    

    143.最大异或对

    #include <iostream>
    using namespace std;
    
    const int N = 100010, M = 31 * N;
    
    int n;
    int a[N], son[M][2], idx;
    
    void insert(int x) {
        int p = 0;
        for (int i = 30; i >= 0; --i) {
            int u = x >> i & 1;
            if (!son[p][u]) son[p][u] = ++idx;
            p = son[p][u];
        }
    }
    
    int query(int x) {
        int p = 0, ans = 0;
        for (int i = 30; i >= 0; --i) {
            int u = x >> i & 1;
            if (son[p][!u]) {
                ans = ans * 2 + !u;
                p = son[p][!u];
            } else {
                p = son[p][u];
                ans = ans * 2 + u;
            }
        }
        return ans;
    }
    
    int main() {
        cin >> n;
        for (int i = 0; i < n; ++i) cin >> a[i];
        
        int ans = 0;
        for (int i = 0; i < n; ++i) {
            insert(a[i]);
            int t = query(a[i]);
            ans = max(ans, a[i] ^ t);
        }
        cout << ans << endl;
        return 0;
    }
    

    836.合并集合

    并查集: 1.将两个集合合并;

    ​ 2.询问两个元素是否在一个集合中。

    基本原理:每个集合用一棵树来表示,树根的编号就是整个集合的编号,每个节点存储它的父节点,p[x]表示它的父节点。

    #include <iostream>
    using namespace std;
    
    const int N = 100010;
    int n, m, p[N];
    
    // 返回x的祖宗节点(路径压缩)
    int find(int x) {
        if (p[x] != x)  p[x] = find(p[x]);
        return p[x];
    }
    
    int main() {
        cin >> n >> m;
        
        for (int i = 1; i <= n; ++i) p[i] = i;
        while (m--) {
            char op[2];
            int a, b;
            cin >> op >> a >> b;
            if (op[0] == 'M') p[find(a)] = find(b);
            else {
                if (find(a) == find(b)) puts("Yes");
                else puts("No");
            }
        }
        return 0;
    }
    

    837.连通块中点的数量

    #include <iostream>
    using namespace std;
    
    const int N = 100010;
    int n, m;
    int p[N], sz[N];
    
    int find(int x) {
        if (x != p[x]) p[x] = find(p[x]);
        return p[x];
    }
    
    int main() {
        cin >> n >> m;
        
        for (int i = 1; i <= n; ++i) p[i] = i, sz[i] = 1;
        
        while (m--) {
            char op[5];
            int a, b;
            cin >> op;
            
            if (op[0] == 'C') {
                cin >> a >> b;
                if (find(a) == find(b)) continue;
                sz[find(b)] += sz[find(a)];
                p[find(a)] = find(b);
            }
            else if (op[1] == '1') {
                cin >> a >> b;
                if (find(a) == find(b)) puts("Yes");
                else puts("No");
            } else {
                cin >> a;
                cout << sz[find(a)] << endl;
            }
        }
        return 0;
    }
    

    838.堆排序

    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 100010;
    int n, m, h[N], sz;
    
    void down(int u) {
        int t = u;
        if (u * 2 <= sz && h[u * 2] < h[t]) t = u * 2;
        if (u * 2 + 1 <= sz && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
        if (u != t) {
            swap(h[u], h[t]);
            down(t);
        }
    }
    
    int main() {
        cin >> n >> m;
        for (int i = 1; i <= n; ++i) cin >> h[i];
        sz = n;
        
        for (int i = n / 2; i; --i) down(i);
        while (m--) {
            cout << h[1] << " ";
            h[1] = h[sz--];
            down(1);
        }
        return 0;
    }
    

    839.模拟堆

    #include <iostream>
    #include <algorithm>
    #include <string.h>
    using namespace std;
    
    const int N = 100010;
    
    int n, m, ph[N], hp[N], h[N], sz;
    
    void heap_swap(int a, int b) {
        swap(ph[hp[a]], ph[hp[b]]);
        swap(hp[a], hp[b]);
        swap(h[a], h[b]);
    }
    
    void down(int u) {
        int t = u;
        if (u * 2 <= sz && h[u * 2] < h[t]) t = u * 2;
        if (u * 2 + 1 <= sz && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
        if (u != t) {
            heap_swap(u, t);
            down(t);
        }
    }
    
    void up(int u) {
        while (u / 2 && h[u / 2] > h[u]) {
            heap_swap(u / 2, u);
            u /= 2;
        }
    } 
    
    int main() {
        cin >> n;
        while (n --) {
            char op[10];
            int k, x;
            cin >> op;
            
            if (!strcmp(op, "I")) {
                cin >> x;
                sz++;
                m++;
                ph[m] = sz, hp[sz] = m;
                h[sz] = x;
                up(sz);
            } else if (!strcmp(op, "PM")) cout << h[1] << endl;
            else if (!strcmp(op, "DM")) {
                heap_swap(1, sz--);
                down(1);
            } else if (!strcmp(op, "D")) {
                cin >> k;
                k = ph[k];
                heap_swap(k, sz);
                sz--;
                down(k), up(k);
            } else {
                cin >> k >> x;
                k = ph[k];
                h[k] = x;
                down(k), up(k);
            }
        }
        return 0;
    }
    

    840.模拟散列表

    哈希表:
    1.存储结构:开放寻址法、拉链法

    2.字符串哈希方式

    //拉链法
    
    #include <iostream>
    #include <cstring>
    
    using namespace std;
    
    const int N = 100003;
    int h[N];
    int e[N], ne[N], idx;
    
    void insert(int x) {
        int k = (x % N + N) % N;
        e[idx] = x, ne[idx] = h[k], h[k] = idx++;
    }
    
    bool find(int x) {
        int k = (x % N + N) % N;
        for (int i = h[k]; i != -1; i = ne[i]) {
            if (e[i] == x) return true;
        }
        return false;
    }
    
    int main() {
        int n;
        cin >> n;
        memset(h, -1, sizeof h);
        while (n--) {
            char op[2];
            int x;
            scanf("%s%d", op, &x);
            
            if (*op == 'I') insert(x);
            else {
                if (find(x)) puts("Yes");
                else puts("No");
            }
        }
        return 0;
    }
    
    // 开放寻址法
    #include <iostream>
    #include <cstring>
    
    using namespace std;
    const int N = 200003, null = 0x3f3f3f3f;
    int h[N];
    
    int find(int x) {
        int k = (x % N + N) % N;
        while (h[k] != null && h[k] != x) {
            ++k;
            if (k == N) k = 0;
        }
        return k;
    }
    
    int main() {
        int n, x;
        cin >> n;
        
        memset(h, 0x3f, sizeof h);
        while (n--) {
            char op[2];
            scanf("%s%d", op, &x);
            
            int k = find(x);
            if (*op == 'I') h[k] = x;
            else {
                if (h[k] != null) puts("Yes");
                else puts("No");
            }
        }
        return 0;
    }
    

    841.字符串哈希

    #include <iostream>
    using namespace std;
    
    const int N = 100010, P = 131;
    typedef unsigned long long ULL;
    char str[N];
    ULL h[N], p[N];
    
    ULL get(int l, int r) {
        return h[r] - h[l - 1] * p[r - l + 1];
    }
    
    int main() {
        int n, m;
        scanf("%d%d%s", &n, &m, str + 1);
    
        p[0] = 1;
        for (int i = 1; i <= n; ++ i) {
            p[i] = p[i - 1] * P;
            h[i] = h[i - 1] * P + str[i];
        }    
        
        while (m--) {
            int l1, l2, r1, r2;
            cin >> l1 >> r1 >> l2 >> r2;
            
            if (get(l1, r1) == get(l2, r2)) puts("Yes");
            else puts("No");
        }
        return 0;
    }
    
  • 相关阅读:
    2020.06.09——习题训练五
    2020.06.01——习题训练4
    2020-05-26 — 习题训练三
    2020-05-22 — 习题训练二-F
    Java笔记(22):IO流(04)
    Java笔记(21):IO流(03)
    Java笔记(20):IO流(02)
    Java笔记(19):IO流(01)
    Java笔记(18):集合框架(04)
    Java笔记(17):集合框架(03)
  • 原文地址:https://www.cnblogs.com/clown9804/p/13598659.html
Copyright © 2020-2023  润新知