1212: [HNOI2004]L语言

题意:给n个单词,m个串,问每个串满足条件的最长前缀,条件:该前缀S能被拆成几个连续的单词(S中的每个字符出现并且唯一出现在某一个单词中)

题解:有dp的思想,假设当前字符的位置为 j,如果当前字符能被理解,则存在 i ∈ (0, j),Si~Sj 是一个单词。因为单词的长度只有20可以暴力向前找。考虑AC自动机,一个节点的fail指向的是以当前串的最长后缀,所以沿着每个节点的fail指针不断向上跳,判断是否存在一个j就行了(单词长度较短,至多跳20次)。

struct node {
    int lengh, fail, Count, vis[26];
    node() {
        mem(vis, 0);
        fail = Count = lengh = 0;
    }
};

struct Acmation {
    int tot, use[2000010];
    node a[300];

    void Inite() {
        tot = 0;
    }
    void Insert(char *s) {
        int n =strlen(s);
        int now = 0;
        rep(i, 0, n) {
            int id = s[i] - 'a';
            if (!a[now].vis[id]) a[now].vis[id] = ++tot;
            now = a[now].vis[id];
        }
        a[now].Count++;
        a[now].lengh = n;
    }
    void getFail() {
        queue<int> q;
        rep(i, 0, 26) if (a[0].vis[i]) {
            a[a[0].vis[i]].fail = 0;
            q.push(a[0].vis[i]);
        }
        while(!q.empty()) {
            int now = q.front();
            q.pop();
            rep(i, 0, 26) {
                if (a[now].vis[i]) {
                    a[a[now].vis[i]].fail = a[a[now].fail].vis[i];
                    q.push(a[now].vis[i]);
                }
                else {
                    a[now].vis[i] = a[a[now].fail].vis[i];
                }
            }
        }
    }
    void Query(char *s) {
        mem(use, 0);
        use[0] = 1;

        int n = strlen(s);
        int now = 0;
        rep(i, 0, n) {
            int id = s[i] - 'a';
            now = a[now].vis[id];
            for (int j = now; j; j = a[j].fail) if (a[j].Count) use[i] |= use[i - a[j].lengh];
        }

        int ans = 0;
        rep(i, 0, n) if (use[i]) ans = max(ans, i + 1);
        pr(ans);
    }
};

int n, m;

Acmation ac;

int main()
{
    ac.Inite();

    sc(n), sc(m);
    rep(i, 0, n) {
        char s[20];
        scanf("%s", s);
        ac.Insert(s);
    }
    ac.getFail();

    char s[2000010];
    rep(i, 0, m) {
        scanf("%s", s);
        ac.Query(s);
    }

    return 0;
}
原文地址:https://www.cnblogs.com/zgglj-com/p/9720726.html