zoukankan      html  css  js  c++  java
  • POJ 数据结构(3)

    数据结构

    trie图的建立和应用,DFA

    hdd2222,poj1204 poj2778, poj3691

    LCARMQ问题

    poj1330

    双端队列和它的应用

    poj2823(单调队列)

    左偏树

    poj3666poj3016

    后缀树,后缀数组

    poj3415,poj3294, poj2774

    poj2758

     

      

    trie图的建立和应用,DFA 

    hdu2222

    很裸的题,可以作为模板:

    View Code
    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    #include <string>
    #include <set>
    #include <ctime>
    #include <queue>
    #include <map>
    #include <sstream>
    
    #define CL(arr, val)    memset(arr, val, sizeof(arr))
    #define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
    #define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
    #define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
    #define L(x)    (x) << 1
    #define R(x)    (x) << 1 | 1
    #define MID(l, r)   (l + r) >> 1
    #define Min(x, y)   x < y ? x : y
    #define Max(x, y)   x < y ? y : x
    #define E(x)    (1 << (x))
    
    const int eps = 1e-6;
    const int inf = ~0u>>2;
    typedef long long LL;
    
    using namespace std;
    
    class Node {
    public:
        Node* fail;
        Node* next[26];
        int cnt;
        Node() {
            CL(next, 0);
            fail = NULL;
            cnt = 0;
        }
    };
    
    //Node* q[10000000];
    
    class AC_automaton : public Node{
    public:
        Node *root;
        int head, tail;
    
        void init() {
            root = new Node();
            head = tail = 0;
        }
    
        void insert(char* st) {
            Node* p = root;
            while(*st) {
                if(p->next[*st-'a'] == NULL) {
                    p->next[*st-'a'] = new Node();
                }
                p = p->next[*st-'a'];
                st++;
            }
            p->cnt++;
        }
    
        void build() {
            root->fail = NULL;
            deque<Node* > q;
            q.push_back(root);
    
            while(!q.empty()) {
                Node* tmp = q.front();
                Node* p = NULL;
                q.pop_front();
                for(int i = 0; i < 26; ++i) {
                    if(tmp->next[i] != NULL) {
                        if(tmp == root) tmp->next[i]->fail = root;
                        else {
                            p = tmp->fail;
                            while(p != NULL) {
                                if(p->next[i] != NULL) {
                                    tmp->next[i]->fail = p->next[i];
                                    break;
                                }
                                p = p->fail;
                            }
                            if(p == NULL)   tmp->next[i]->fail = root;
                        }
                        q.push_back(tmp->next[i]);
                    }
                }
            }
        }
    
        int search(char* st) {
            int cnt = 0, t;
            Node* p = root;
            while(*st) {
                t = *st - 'a';
                while(p->next[t] == NULL && p != root) {
                    p = p->fail;
                }
                p = p->next[t];
                if(p == NULL)   p = root;
    
                Node* tmp = p;
                while(tmp != root && tmp->cnt != -1) {
                    cnt += tmp->cnt;
                    tmp->cnt = -1;
                    tmp = tmp->fail;
                }
                st++;
            }
            return cnt;
        }
    }AC;
    
    char dic[100], st[1000010];
    
    int main() {
        freopen("data.in", "r", stdin);
    
        int t, n, ans;
        scanf("%d", &t);
    
        while(t--) {
            scanf("%d", &n);
            AC.init();
            while(n--) {
                scanf("%s", dic);
                AC.insert(dic);
            }
            AC.build();
            scanf("%s", st);
            ans = AC.search(st);
            cout << ans << endl;
        }
        return 0;
    }

    poj 1204

    题意是给一个字符串矩阵。然后给一些模式串,问这个模式串在矩阵的哪个位置被找到(可以从矩阵中的某个点向八个方向扩展)。。。输出开始坐标和方向。

    解:用trie图写的,看得gw老师的课件。。。对模式串反向建trie图就可以,好蛋疼的是模式串为

    ABC

    ABCDEF

    这种形式。。。需要加一个vector记录危险节点为A的所有串的编号。。。

    从早晨一直搞。。。终于搞过了,拍了近4.5k的代码。。。

    详见代码:

    View Code
    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    #include <string>
    #include <set>
    #include <ctime>
    #include <queue>
    #include <map>
    #include <sstream>
    
    #define CL(arr, val)    memset(arr, val, sizeof(arr))
    #define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
    #define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
    #define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
    #define L(x)    (x) << 1
    #define R(x)    (x) << 1 | 1
    #define MID(l, r)   (l + r) >> 1
    #define Min(x, y)   x < y ? x : y
    #define Max(x, y)   x < y ? y : x
    #define E(x)    (1 << (x))
    
    const int eps = 1e-6;
    const int inf = ~0u>>2;
    typedef long long LL;
    
    using namespace std;
    
    const int N = 1024;
    const int LET = 26;
    int nNodesCount = 0;
    
    struct CNode {
        CNode * ch[LET];
        CNode * pPre;
        vector<int> bstopNode;
        int num;
        CNode() {
            CL(ch, 0);
            bstopNode.clear();
            pPre = NULL;
        }
    };
    
    CNode T[100000];
    char mp[N][N];
    int r, c, m;
    bool vis[N] = {false};
    
    
    int dir[8][2] = {{-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}};
    
    void insert(CNode* p, char* s, int x) {
        int i, l = strlen(s);
        for(i = l - 1; i >= 0; --i) {
            if(p->ch[s[i]-'A'] == NULL) {
                p->ch[s[i]-'A'] = T + nNodesCount++;
            }
            p = p->ch[s[i] - 'A'];
        }
        p->bstopNode.push_back(x);
    }
    
    void buildDFA() {
        int i;
        for(i = 0; i < LET; ++i) {
            T[0].ch[i] = T + 1;
        }
        T[0].pPre = NULL;
        T[1].pPre = T;
    
        deque<CNode *> q;
        q.push_back(T + 1);
    
        while(!q.empty()) {
            CNode * proot = q.front();
            q.pop_front();
            for(i = 0; i < LET; ++i) {
                CNode* p = proot->ch[i];
    
                if(p) {
                    CNode* father = proot->pPre;
                    while(father) {
                        if(father->ch[i]) {
                            p->pPre = father->ch[i];
    
                            if(p->pPre->bstopNode.size() != 0) {
                                vector<int>::iterator it;
                                for(it = p->pPre->bstopNode.begin(); it != p->pPre->bstopNode.end(); ++it)
                                    p->bstopNode.push_back(*it);
                            }
    
                            break;
                        } else
                            father = father->pPre;
                    }
                    q.push_back(p);
                }
            }
        }
    }
    
    bool inmap(int x, int y) {
        if(x < 0 || x >= r || y < 0 || y >= c)  return false;
        return true;
    }
    
    struct node {
        int x, y;
        char c;
        node() {}
        node(int a, int b, char d) : x(a), y(b), c(d) {}
    } ans[10000];
    
    bool search(int sx, int sy, int d) {
        CNode* p = T + 1;
        int x, y;
        for(x = sx, y = sy; inmap(x, y); x += dir[d][0], y += dir[d][1]) {
            while(true) {
                if(p->ch[mp[x][y] - 'A']) {
                    p = p->ch[mp[x][y] - 'A'];
                    if(p->bstopNode.size() != 0) {
                        //printf("%d %d %d\n", x, y, p->num);
                        vector<int>::iterator it;
                        for(it = p->bstopNode.begin(); it != p->bstopNode.end(); ++it)
                            if(!vis[*it]) {
                                ans[*it] = node(x, y, (d + 4)%8 + 'A');
                                vis[*it] = true;
                            }
                        //return true;
                    }
                    break;
                } else  p = p->pPre;
            }
        }
        return false;
    }
    
    void solve() {
        buildDFA();
        int i;
        for(i = 0; i < r; ++i) {
            search(i, 0, 2);
            search(i, 0, 1);
            search(i, 0, 3);
            search(i, c - 1, 6);
            search(i, c - 1, 5);
            search(i, c - 1, 7);
        }
        for(i = 0; i < c; ++i) {
            search(0, i, 4);
            search(0, i, 5);
            search(0, i, 3);
            search(r - 1, i, 0);
            search(r - 1, i, 1);
            search(r - 1, i, 7);
        }
    }
    
    int main() {
        //freopen("data.in", "r", stdin);
    
        int i;
        scanf("%d%d%d", &r, &c, &m);
        for(i = 0; i < r; ++i) {
            scanf("%s", mp[i]);
        }
        char st[N];
        nNodesCount = 2;
        for(i = 0; i < m; ++i) {
            scanf("%s", st);
            insert(T + 1, st, i);
        }
        solve();
        for(i = 0; i < m; ++i) {
            printf("%d %d %c\n", ans[i].x, ans[i].y, ans[i].c);
        }
        return 0;
    }

     poj 2278&&3691

    http://www.cnblogs.com/vongang/archive/2012/11/06/2756422.html

    LCARMQ问题 

    poj 1330

    题意很裸,就是求LCA。

    LCA转化为RMQ的方法:http://www.cnblogs.com/vongang/archive/2012/05/03/2481196.html

    RMQ写搓了。。。wa了3次。。。

    谨记!

    View Code
    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    #include <string>
    #include <set>
    #include <ctime>
    #include <queue>
    #include <map>
    #include <sstream>
    
    #define CL(arr, val)    memset(arr, val, sizeof(arr))
    #define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
    #define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
    #define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
    #define L(x)    (x) << 1
    #define R(x)    (x) << 1 | 1
    #define MID(l, r)   (l + r) >> 1
    #define Min(x, y)   x < y ? x : y
    #define Max(x, y)   x < y ? y : x
    #define E(x)    (1 << (x))
    
    const int eps = 1e-6;
    const int inf = ~0u>>2;
    typedef long long LL;
    
    using namespace std;
    
    const int N = 20010;
    
    
    int D[N], E[N], R[N];
    
    class RMQ {
    public:
        int Min[N][20];
        void build(int n) {
            int i, j, m;
            for(i = 1; i <= n; ++i) Min[i][0] = i;
            m = int(log(double(n))/log(2.0));
            FOR(j, 1, m) {
                FOR(i, 1, n - (1<<j) + 1) {
                    if(D[Min[i][j-1]] < D[Min[i+(1<<(j-1))][j-1]]) {
                        Min[i][j] = Min[i][j-1];
                    } else {
                        Min[i][j] = Min[i+(1<<(j-1))][j-1];
                    }
    
                }
            }
        }
    
        int query(int s, int e) {
            int k = log(double(e - s + 1))/log(2.0);
            if(D[Min[s][k]] < D[Min[e-(1<<k) + 1][k]])   return  Min[s][k];
            else    return Min[e-(1<<k) + 1][k];
        }
    } Q;
    
    vector<int> g[N];
    
    int in[N], cnt;
    bool vis[N];
    
    void init(int n) {
        CL(in, 0); CL(D, 0);
        CL(E, 0); CL(R, 0);
        CL(vis, 0); cnt = 1;
        for(int i = 1; i <= n; ++i) {
            g[i].clear();
        }
    }
    
    void dfs(int t, int dep) {
        if(!vis[t]) {
            R[t] = cnt;
            vis[t] = true;
        }
    
        D[cnt] = dep;
        E[cnt++] = t;
        for(int i = 0; i < int(g[t].size()); ++i) {
            dfs(g[t][i], dep + 1);
            D[cnt] = dep;
            E[cnt++] = t;
        }
    }
    
    int main() {
        //freopen("data.in", "r", stdin);
    
        int t, i, n, x, y;
        scanf("%d", &t);
        while(t--) {
    
            scanf("%d", &n);
            init(n);
            REP(i, n - 1) {
                scanf("%d%d", &x, &y);
                g[x].push_back(y);
                in[y]++;
            }
            FOR(i, 1, n) {
                if(in[i] == 0)  {
                    dfs(i, 0);
                    break;
                }
            }
            cnt--;
            Q.build(cnt);
    
            scanf("%d%d", &x, &y);
            x = R[x], y = R[y];
            if(x > y)   swap(x, y);
            printf("%d\n", E[Q.query(x, y)]);
        }
        return 0;
    }

    双端队列和它的应用 

    poj 2823 (单调队列)

    单调队列的原理是双端队列,好吧,我只能说这个标题没有错。。。

    单调队列的思想是保证窗口的元素的value是从前往后是依次减小(增大)的。还有一个值就是当前value的position,也就是说窗口里所有元素的position都必须跟当前待插入的元素的position的距离相差小于等于窗口的大小。(-_-! 说的好别扭)

    View Code
    // 单调队列模板
    
    const int N = 1000010;
    
    class Node {
    public:
        int pos;
        int num;
        Node() {};
        Node(int _a, int _b) : pos(_a), num(_b) {}
    };
    
    class Dequ{
        Node deq[N];
    public:
        void Get_Min(int ans[], int _num[], int n, int k) {
            int i, head, tail;
            head = tail = 0;
            REP(i, n) {
                if(head < tail && deq[head].pos <= i - k)   head++;
                while(head < tail && deq[tail-1].num >= _num[i])    tail--;
    
                deq[tail++] = Node(i, _num[i]);
                ans[i] = deq[head].num;
            }
        }
        void Get_Max(int ans[], int _num[], int n, int k) {
            int i, head, tail;
            head = tail = 0;
            REP(i, n) {
                if(head < tail && deq[head].pos <= i - k)   head++;
                while(head < tail && deq[tail-1].num <= _num[i])    tail--;
    
                deq[tail++] = Node(i, _num[i]);
                ans[i] = deq[head].num;
            }
        }
    } Dequeue;

    左偏树 

    poj 3666

    只知道dp的解法。。。左偏树维护中位数真心没看懂。。

    先对序列排下序,用排好序的下标代表那个数(算是离散化吧)。

    dp[i[[j] 到第i个位置,高度为[1...j]中任意一个的最小花费。

    dp[i][j] = dp[i-1][j] + iabs(A[j] - A[i])
    if(j > 0)  dp[i][j] = min(dp[i][j-1], dp[i][j];
  • 相关阅读:
    201506022038_《JavaScript权威指南》(p48-58)
    201506022038_《JavaScript权威指南-判断两个数组相等》(p38-48)
    201506021641_《JavaScript权威指南》(p25-38)
    Linux平台上转换文件编码
    一台服务器上部署多个Terracotta的方法
    Subversion Backup and Restore
    How to name a slf4j logger
    基于ScheduledExecutorService的并发定时任务处理能力测试
    CodeReview of JDK Source Code
    Share Keyboard, Mouse and Clipboard between Multiple Computers
  • 原文地址:https://www.cnblogs.com/vongang/p/2598655.html
Copyright © 2011-2022 走看看