• Gym101741K Consistent Occurrences(AC自动机)


    多模式串匹配问题,因为要求每个串不重复出现的次数,我们只需要对于每个串维护一个len,如果匹配到当前串的末尾并且到之前匹配的长度大于等于len,那么说明是新的答案

    我采用的方法是对于每个独立串的末尾标记一下,这样我们去做自动机的时候就能够知道是否匹配,但是每次都要走到根,因为这样才可以覆盖到所有的串。

    但是有个问题,字符串不一定不等,因此我们哈希一下,对于相同的字符串,只做第一个,后面的答案跟他一样即可

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=5e5+10;
    struct node{
        int cnt;
        node * nxt[27];
        node * fail;
        vector<node *> num;
    }*rt;
    node pool[N];
    node *pos[N];
    int n,m,idx;
    int cnt[N];
    int len[N];
    int id[N];
    int last[N];
    string s;
    map<string,int> m1;
    int dd[N];
    void insert(string s,int x){
        node *p=rt;
        int i;
        for(i=0;i<s.size();i++){
            int sign=s[i]-'a';
            if(p->nxt[sign]==NULL)
                p->nxt[sign]=pool+(++idx);
            p=p->nxt[sign];
            if(i==(int)s.size()-1&&!p->cnt){
                p->cnt=x;
            }
        }
    }
    void build(){
        int i;
        queue<node *> q;
        rt->fail=rt;
        for(i=0;i<26;i++){
            if(rt->nxt[i]){
                rt->nxt[i]->fail=rt;
                rt->num.push_back(rt->nxt[i]);
                q.push(rt->nxt[i]);
            }
            else{
                rt->nxt[i]=rt;
                rt->nxt[i]->fail=rt;
            }
        }
        while(q.size()){
            auto t=q.front();
            q.pop();
            for(i=0;i<26;i++){
                if(t->nxt[i]){
                    t->nxt[i]->fail=t->fail->nxt[i];
                    t->fail->nxt[i]->num.push_back(t->nxt[i]);
                    q.push(t->nxt[i]);
                }
                else{
                    t->nxt[i]=t->fail->nxt[i];
                }
            }
        }
    }
    void query(){
        int i;
        node *p=rt;
        memset(last,-1,sizeof last);
        for(i=0;i<n;i++){
            int sign=s[i]-'a';
            p=p->nxt[sign];
            node *tmp=p;
            while(p!=rt){
                if(p->cnt){
                    if(i-last[p->cnt]>=len[p->cnt]){
                        cnt[p->cnt]++;
                        last[p->cnt]=i;
                    }
                }
                p=p->fail;
            }
            p=tmp;
        }
    }
    int main(){
        ios::sync_with_stdio(false);
        cin>>n>>m;
        int i;
        rt=pool;
        cin>>s;
        for(i=1;i<=m;i++){
            string s1;
            cin>>s1;
            len[i]=(int)s1.size();
            insert(s1,i);
            if(m1[s1]){
                dd[i]=m1[s1];
            }
            else{
                m1[s1]=i;
            }
        }
        build();
        query();
        for(i=1;i<=m;i++){
            if(dd[i])
                cnt[i]=cnt[dd[i]];
            cout<<cnt[i]<<endl;
        }
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    设置ios中imageView图片自适应,
    IOS应用之间调用
    XCode debug中添加查找debug和控制台的办法
    初学Java scirpt(判断、循环语句)
    Java Script 字符串操作
    初学 Java Script (算数运算及逻辑术语)
    Ubuntu 配置JDK
    SQL Server 跨库复制表方法小笔记
    Ubuntu 重装 mysql
    Java Script 数组操作
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13899927.html
Copyright © 2020-2023  润新知