zoukankan      html  css  js  c++  java
  • Bazinga HDU

    http://acm.hdu.edu.cn/showproblem.php?pid=5510

    想了很久队友叫我用ufs + kmp暴力过去了。

    fa[x] = y表示x是y的子串,所以只有fa[x] == x才需要kmp一次。

    那么这样的话,如果全部都不互为子串的话,复杂度还是爆咋的。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <string>
    #include <stack>
    #include <map>
    #include <set>
    #include <bitset>
    #include <cstdlib>
    #include <ctime>
    #define X first
    #define Y second
    #define clr(u,v); memset(u,v,sizeof(u));
    #define in() freopen("data.txt","r",stdin);
    #define out() freopen("ans","w",stdout);
    #define Clear(Q); while (!Q.empty()) Q.pop();
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    const ll INF = 1e17;
    const int inf = 0x3f3f3f3f;
    const int maxn = 2000 + 2;
    int tonext[502][maxn];
    void get_next(char sub[], int tonext[], int lensub) {
        int i = 1, j = 0;
        tonext[1] = 0;
        while (i <= lensub) {
            if (j == 0 || sub[i] == sub[j]) {
                tonext[++i] = ++j;
            } else j = tonext[j];
        }
    }
    int kmp(char str[], char sub[], int lenstr, int lensub, int tonext[]) {
        int i = 1, j = 1;
        while (i <= lenstr) {
            if (j == 0 || str[i] == sub[j]) {
                ++i, ++j;
            } else j = tonext[j];
            if (j == lensub + 1) return true;
        }
        return false;
    }
    char str[502][maxn];
    int len[502];
    int f;
    int fa[maxn];
    int tofind(int u) {
        if (fa[u] == u) return u;
        else return fa[u] = tofind(fa[u]);
    }
    void tomerge(int x, int y) {
        x = tofind(x), y = tofind(y);
        fa[y] = x;
    }
    void work() {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) {
            scanf("%s", str[i] + 1);
            len[i] = strlen(str[i] + 1);
            get_next(str[i], tonext[i], len[i]);
            fa[i] = i;
        }
        printf("Case #%d: ", ++f);
        int ans = -1;
        for (int i = 2; i <= n; ++i) {
            for (int j = i - 1; j >= 1; --j) {
                if (tofind(j) != j) continue;
                if (kmp(str[i], str[j], len[i], len[j], tonext[j])) {
                    tomerge(i, j); //合并的方向,小的合并去大的
                } else {
                    ans = i;
                }
    //            if (kmp(str[j], str[i], len[j], len[i], tonext[i])) {
    //                tomerge(j, i);
    //            }
            }
        }
        printf("%d
    ", ans);
        return;
    }
    
    int main() {
    #ifdef local
        in();
    #else
    #endif
        int t;
        scanf("%d", &t);
        while (t--) work();
        return 0;
    }
    View Code

    有一个超时的AC自动机算法。复杂度O(T * n * lenstr * lenstr)

    首先所有串buildFail

    然后对于每一个串,爬Fail树。从后往前枚举

    那么每个串跑一次Fail树的时候就能知道有多少个子串。成立的条件是子串个数 < i,则i位置成立。

    如果后面的串使得匹配子串个数变大的话,那么是不影响的,说明在后面枚举的时候那个位置就应该是已经成立的了。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <string>
    #include <stack>
    #include <map>
    #include <set>
    #include <bitset>
    #include <cstdlib>
    #include <ctime>
    #define X first
    #define Y second
    #define clr(u,v); memset(u,v,sizeof(u));
    #define in() freopen("2.h","r",stdin);
    #define out() freopen("ans","w",stdout);
    #define Clear(Q); while (!Q.empty()) Q.pop();
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    const ll INF = 1e17;
    const int inf = 0x3f3f3f3f;
    char str[52][2000 + 20];
    struct Node {
        int flag, id;
        struct Node *Fail;
        struct Node *pNext[26];
    } tree[1000000 + 20];
    int t;
    struct Node * create() {
        struct Node * p = &tree[t++];
        p->flag = 0;
        p->Fail = NULL;
        p->id = t - 1;
        for (int i = 0; i < 26; ++i) p->pNext[i] = NULL;
        return p;
    }
    void toinsert(struct Node **T, char str[]) {
        struct Node *p = *T;
        if (p == NULL) p = *T = create();
        for (int i = 1; str[i]; ++i) {
            int id = str[i] - 'a';
            if (p->pNext[id] == NULL) {
                p->pNext[id] = create();
            }
            p = p->pNext[id];
        }
        p->flag++;
    }
    struct Node * que[1000000 + 20];
    void BuildFlag(struct Node **T) {
        struct Node *p = *T;
        struct Node *root = *T;
        if (p == NULL) return ;
        int head = 0, tail = 0;
        que[tail++] = root;
        while (head < tail) {
            p = que[head];
            for (int i = 0; i < 26; ++i) {
                if (p->pNext[i] != NULL) {
                    if (p == root) {
                        p->pNext[i]->Fail = root;
                    } else {
                        struct Node * FailNode = p->Fail;
                        while (FailNode != NULL) {
                            if (FailNode->pNext[i] != NULL) {
                                p->pNext[i]->Fail = FailNode->pNext[i];
                                break;
                            }
                            FailNode = FailNode->Fail;
                        }
                    }
                    que[tail++] = p->pNext[i];
                } else if (p == root) {
                    p->pNext[i] = root;
                } else {
                    p->pNext[i] = p->Fail->pNext[i];
                }
            }
            head++;
        }
    }
    int vis[1000000 + 20], DFN;
    int searchAC(struct Node *T, char str[], int val) {
        DFN++;
        int ans = 0;
        struct Node * p = T;
        struct Node * root = T;
        if (p == NULL) return 0;
        for (int i = 1; str[i]; ++i) {
            int id = str[i] - 'a';
            p = p->pNext[id];
            struct Node * temp = p;
            while (temp != root && vis[temp->id] != DFN) {
                vis[temp->id] = DFN;
                ans += temp->flag;
                temp = temp->Fail;
                if (ans >= val) return false;
            }
        }
        return true;
    }
    int f;
    void work() {
        t = 0;
        printf("Case #%d: ", ++f);
        int n;
        scanf("%d", &n);
        struct Node * T = NULL;
        for (int i = 1; i <= n; ++i) {
            scanf("%s", str[i] + 1);
            toinsert(&T, str[i]);
        }
        BuildFlag(&T);
        for (int i = n; i ; --i) {
            if(searchAC(T, str[i], i)) {
                printf("%d
    ", i);
                return;
            }
        }
        printf("-1
    ");
        return;
    }
    
    int main() {
    #ifdef LOCAL
        in();
    #else
    #endif
        int t;
        scanf("%d", &t);
        while (t--) work();
        return 0;
    }
    View Code
  • 相关阅读:
    深度剖析Byteart Retail案例
    REVIT使用中遇到的各种问题汇总
    常用设计规范
    编程修养
    Linux、Windows静态编译ffmpeg 4.4.1、x264、x265等编解码库的脚本
    程序员的灯下黑:重知识轻技术
    GitHub 公布 2021 Top 10 博文「GitHub 热点速览」
    狠人!标星 3.4 万的项目说删就删,几行代码搞崩数万个开源项目
    重装系统前备份fstab
    Ubuntu系统下制作U盘启动盘
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/7407035.html
Copyright © 2011-2022 走看看