• 字符串训练之八


    https://www.luogu.org/problem/P3966

    分析:

    比较普通的AC自动机,这个题唯一不同的就是询问有很多个,但询问的又是模式串

    所以建完自动机后暴力询问肯定会Tle

    考虑过程跳fail指针的过程

    每一个节点保存一下属于多少字符串,为它的权值。

    然后一个节点表示的字符串在整个字典中出现的次数相当于其在Fail树中的子树的权值的和

    code :

    include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define N 1100005
    using namespace std;
    int n,a[N],h[N],cnt,last,ch[N][26],sz[N],fail[N];
    char s[N];
    struct ac{
        void ins(int x){
            scanf("%s",s+1);int now=0,len=strlen(s+1);
            for(int i=1;i<=len;i++){
                int u=s[i]-'a';
                if(!ch[now][u]) ch[now][u]=++cnt;
                now=ch[now][u];
                sz[now]++;
            }
            a[x]=now;
        }
        void build(){
            int i,head=0,tail=0;
            for(i=0;i<26;i++) if(ch[0][i]) h[++tail]=ch[0][i];
            while(head<tail){
                int x=h[++head],y;
                    for(i=0;i<26;i++) if(y=ch[x][i]){
                    h[++tail]=y;
                    fail[y]=ch[fail[x]][i];
                }
                else ch[x][i]=ch[fail[x]][i];
            }
        }
        void solve(){
            for(int i=cnt;i>=0;i--) sz[fail[h[i]]]+=sz[h[i]];
            for(int i=1;i<=n;i++) printf("%d
    ",sz[a[i]]);
        }
    }ac;
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++) ac.ins(i);
        ac.build();ac.solve();
        return 0;
    }
    

    当然如果你不会AC自动机还有哈希的做法:

    code:

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #define f(x,y,z) for(int x=y;x<=z;x++)
    #define F(x,y,z,v) for(int x=y;x<=z;x+=v)
    using namespace std;
    const int MAXN=1000005;
    char a[205][MAXN],b[MAXN<<1];
    unsigned long long hash1[205],hash2[MAXN<<1],divi[MAXN<<1];
    int stl[205];
    const int BASE=131;
    unsigned long long getsum(int l,int r)
    {
        return hash2[r]-hash2[l-1]*divi[r-l+1];
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        int cnt=-1,len;
        f(i,1,n)
        {
            b[++cnt]='#';
            scanf("%s",&a[i]);
            len=strlen(a[i]);
            stl[i]=len;
            f(j,0,len-1)
            {
                b[++cnt]=a[i][j];
                hash1[i]*=BASE;
                hash1[i]+=a[i][j];
            }
        }
        len=strlen(b);
        hash2[0]=b[0];
        divi[0]=1;
        f(i,1,len-1)
        {
            hash2[i]=hash2[i-1]*BASE+b[i];
            divi[i]=divi[i-1]*BASE;
        }
        f(i,1,n)
        {
            int tcnt=0;
            f(j,1,len-stl[i])
                if(hash1[i]==getsum(j,j+stl[i]-1))
                    tcnt++;
            printf("%d
    ",tcnt);
        }
        return 0;
    }
    
  • 相关阅读:
    MapReduce -- 统计天气信息
    设计模式--策略模式
    基于物品的协同过滤(二)
    Hadoop应用开发,常见错误
    基于物品的协同过滤(一)
    基于用户的协同过滤
    MapReduce开发程序,运行环境配置
    3DES加解密 C语言
    js获取对象位置的方法
    icheck.js的一个简单demo
  • 原文地址:https://www.cnblogs.com/wzxbeliever/p/11766951.html
Copyright © 2020-2023  润新知