• 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;
    }
  • 相关阅读:
    【Android
    【数据结构】之链表(C语言描述)
    【数据结构】之顺序表(C语言描述)
    【Android
    【Android
    【Android
    【Android
    【Android
    在线HTTP速度测试(响应时间测试)及浏览器兼容测试
    阿里云 腾讯云 服务器挂载数据盘
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/9216762.html
Copyright © 2020-2023  润新知