zoukankan      html  css  js  c++  java
  • ac自动机

    给定n个模式串和1个文本串,求有多少个模式串在文本串里出现过。

    #include <bits/stdc++.h>
    const int maxn = 3*1e6+5, M = 1e6+7;
    using namespace std;
    int siz, cur[maxn];
    bool flag[maxn];
    struct ac{
        struct Sta{
            int son[26], fail;
            int cnt, rr;
        }sta[maxn];
        void init(){
            siz = 1;
        }
        void insert(char *S, int tot){
            int len = strlen(S);
            int now = 0;
    
            for(int i = 0; i < len; i++){
                char c = S[i];
                if(sta[now].son[c-'a'] == 0)
                    sta[now].son[c-'a'] = siz++;
                now = sta[now].son[c-'a'];
            }
            sta[now].cnt++;
        };
    
        void build(){
            queue <int> Q;
    
            Q.push(0);
    
            while(!Q.empty()){
                int u = Q.front(); Q.pop();
                for(int i = 0; i < 26; i++){
                    if(sta[u].son[i]){
                        if(u == 0)sta[sta[u].son[i]].fail = 0;
                        else 
                            sta[sta[u].son[i]].fail = sta[sta[u].fail].son[i]; 
                        Q.push(sta[u].son[i]);
                    }
                    else sta[u].son[i] = sta[sta[u].fail].son[i];
                }
            }
        }
    
        int match(char *S){
            int now = 0, res = 0;
            int len = strlen(S);
            for(int i = 0; i < len; i++){
                char c = S[i];
                now = sta[now].son[c - 'a'];
                for(int t = now; t && !flag[t]; t = sta[t].fail)
                    res += sta[t].cnt, flag[t] = 1;
            }
            return res;
        }
        int Query(int t){
            return sta[cur[t]].rr;
        }
    
    }Tr;
    char a[maxn][55];
    char s[M];
    char S[M];
    int main()
    {
        int n ,m;
        scanf("%d", &n);
        Tr.init();
        for(int i = 1; i <= n; i++){
           // scanf("
    ");
            scanf("%s", s);
            Tr.insert(s, i);
        }
        Tr.build();
       // scanf("
    ");
        scanf("%s", S);
        printf("%d
    ", Tr.match(S));
        return 0;
    }

    有 NN 个由小写字母组成的模式串以及一个文本串 TT 。每个模式串可能会在文本串中出现多次。你需要找出哪些模式串在文本串 TT 中出现的次数最多。

    #include <bits/stdc++.h>
    const int maxn = 3*1e6+5, M = 1e6+7;
    using namespace std;
    int siz;
    bool flag[maxn];
    struct Result{
        int sum , id;
    }ans[M];
    struct ac{
        struct Sta{
            int son[26], fail;
            int end, rr;
        }sta[maxn];
        void clear(int x){
            memset(sta[x].son, 0, sizeof(sta[x].son));
            sta[x].end = sta[x].fail = 0;
        }
        void insert(char *S, int tot){
            int len = strlen(S);
            int now = 0;
    
            for(int i = 0; i < len; i++){
                char c = S[i];
                if(sta[now].son[c-'a'] == 0){
                    sta[now].son[c-'a'] = ++siz;
                    clear(siz);
                }    
                now = sta[now].son[c-'a']; 
            }
            sta[now].end = tot;
        };
    
        void build(){
            queue <int> Q;
    
            Q.push(0);
    
            while(!Q.empty()){
                int u = Q.front(); Q.pop();
                for(int i = 0; i < 26; i++){
                    if(sta[u].son[i]){
                        if(u == 0)sta[sta[u].son[i]].fail = 0;
                        else 
                            sta[sta[u].son[i]].fail = sta[sta[u].fail].son[i]; 
                        Q.push(sta[u].son[i]);
                    }
                    else sta[u].son[i] = sta[sta[u].fail].son[i];
                }
            }
        }
    
        void match(char *S){
            int now = 0, res = 0;
            int len = strlen(S);
            for(int i = 0; i < len; i++){
                char c = S[i];
                now = sta[now].son[c - 'a'];
                for(int t = now; t; t = sta[t].fail)
                    ans[sta[t].end].sum++;
            }
        }
    }Tr;
    char a[M][75];
    char S[M];
    bool cmp(Result a, Result b){
        return a.sum == b.sum ? a.id < b.id : a.sum > b.sum;
    }
    int main()
    {
        int n ,m;
        while(scanf("%d", &n) == 1){
            if(!n)break;
            siz = 0;
            for(int i = 1; i <= n; i++){
                ans[i].id = i;
                ans[i].sum = 0;
            }
            Tr.clear(0);
            for(int i = 1; i <= n; i++){
                scanf("%s", a[i]);
                Tr.insert(a[i], i);
            }
            Tr.build();
            scanf("%s", S);
            Tr.match(S);
            sort(ans+1, ans+1+n, cmp);
            printf("%d
    ", ans[1].sum);
            for(int i = 1; i <= n; i++){
                if(ans[i].sum < ans[1].sum)break;
                printf("%s
    ", a[ans[i].id]);
            }    
        }
        
        return 0;
    }
  • 相关阅读:
    Internet Explorer 安全区域注册表项说明
    Android强制设置横屏或竖屏
    SQLite to Asp.net Entity Framework 部署问题
    获取地里位置信息
    通信API、使用Web Workers处理线程
    本地存储、离线应用程序
    多媒体播放
    绘制图形
    表单与文件
    HTML5的结构
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/9216762.html
Copyright © 2011-2022 走看看