首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

LA 4670 AC自动机容易题

2013-02-24 
LA 4670 AC自动机简单题题目链接题意:给你n个子串(小写字母, n 150, len 70),给你个文本串(len 1

LA 4670 AC自动机简单题

题目链接

题意:给你n个子串(小写字母, n <= 150, len <= 70),给你个文本串(len <= 10^6), 让你找到在文本串中出现次数最多的子串, 输出最多次数和子串。

注意:如果出现次数最多的有很多子串,要全部输出,还有n个子串会有重复。

做法:trie的每个节点用一个vector记录以该节点结尾的单词的标号,find()函数用数组cnt[]下标保存单词标号,值保存次数。然后扫描一下即可。

#include <cstdio>#include <cstring>#include <queue>#include <vector>#include <algorithm>using namespace std;const int maxn = 10004 * 51;int n;char s[1000006], str[155][77];int cnt[155];struct AC {    int c[maxn][26], tot, f[maxn];vector <int> id[maxn];     int idx(char c) { return c-'a'; }    int new_node() {        memset(c[tot], 0, sizeof(c[tot]));        id[tot].clear();        return tot++;    }    void init() { tot = 0; new_node(); }    void insert(char *s, int pos) {        int i, j, u = 0, n = strlen(s);        for(i = 0; i < n; i++) {            int k = idx(s[i]);            if(!c[u][k]) c[u][k] = new_node();            u = c[u][k];        }        id[u].push_back(pos);    }    void getfail() {        int i, j, u, v;        queue <int> q;        f[0] = 0;        for(i = 0; i < 26; i++) {            u = c[0][i];            if(u) { f[u] = 0; q.push(u); }        }        while(!q.empty()) {            u = q.front(); q.pop();            for(i = 0; i < 26; i++) {                v = c[u][i];                if(!v) { c[u][i] = c[f[u]][i]; continue; } // 这行是AC自动机改造: 没改造的是这样的 if(!v) continue;                 j = f[u];                while(j && !c[j][i]) j = f[j];                f[v] = c[j][i];                q.push(v);            }        }    }    void find(char *s) {        int i, j, u = 0, n = strlen(s);        for(i = 0; i < n; i++) {            int k = idx(s[i]);//while(u && !c[u][k]) u = f[u]; // 改造后的AC自动机,这句话不用写            u = c[u][k];            for(j = u; j; j = f[j]) {                for(int k = 0; k < id[j].size(); k++)cnt[id[j][k]]++;            }        }     }}ac;int main() {    int i, j;      while( ~scanf("%d", &n) && n) {        ac.init();memset(cnt, 0, sizeof(cnt));        for(i = 1; i <= n; i++) {            scanf("%s", str[i]);            ac.insert(str[i], i);        }        ac.getfail();        scanf("%s", s);        ac.find(s);int ans = 0;for(i = 1; i <= n; i++)if(ans < cnt[i]) ans = cnt[i];printf("%d\n", ans);for(i = 1; i <= n; i++)if(ans == cnt[i]) puts(str[i]);    }    return 0;}


热点排行