zoukankan      html  css  js  c++  java
  • P3966 [TJOI2013]单词

    传送门

    AC自动机

    一看就知道是AC自动机

    它问的是每一个单词在所有单词中出现的次数

    对所有单词搞一个AC自动机

    然后把所有单词连在一起,中间用一个不会出现的字符或者其他什么的隔开

    然后把连在一起的串放到AC自动机上搞匹配就行了

    要注意单词可能有重复

    所以要把重复的单词判一下

    具体看代码

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int N=1e6+7;
    int n,mp[207];
    char s[N];
    int c[N][27],pd[N],fail[N],g[N],cnt;
    char a[N]; int b[N+207],len;
    inline void ins(int num)//插入单词
    {
        int u=0,l=strlen(a);
        for(int i=0;i<l;i++)
        {
            int v=a[i]-'a'+1;
            b[++len]=v;//把匹配串处理一下
            if(!c[u][v]) c[u][v]=++cnt;
            u=c[u][v];
        }
        if(!pd[u]) pd[u]=num;
        mp[num]=pd[u];//用来处理重复的单词,mp[i]表示第i个单词最早出现时的位置
        b[++len]=-1;//单词之间用-1隔开
    }
    queue <int> q;
    inline void pre()//预处理fail和g,g[x]表示从x一直走失配边,走到的第一个结束标记的位置
    {
        for(int i=1;i<=26;i++)
            if(c[0][i]) q.push(c[0][i]);
        while(!q.empty())
        {
            int u=q.front(); q.pop();
            for(int i=1;i<=26;i++)
            {
                int v=c[u][i];
                if(!v) c[u][i]=c[fail[u]][i];
                else
                {
                    fail[v]=c[fail[u]][i];
                    g[v]= pd[fail[v]] ? fail[v] : g[fail[v]];
                    q.push(v);
                }
            }
        }
    }
    int ans[207];
    inline void query()//匹配
    {
        int u=0;
        for(int i=1;i<=len;i++)
        {
            if(b[i]==-1)//如果走到分隔标记,就回到起点匹配
            {
                u=0;
                continue;
            }
            u=c[u][b[i]];
            if(pd[u]) ans[pd[u]]++;
            for(int j=g[u];j;j=g[j])
                ans[pd[j]]++;
        }
        for(int i=1;i<=n;i++)
            printf("%d
    ",ans[mp[i]]);
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",a);
            ins(i);
        }
        pre();
        query();
        return 0;
    }
  • 相关阅读:
    PCL配置即常见问题
    opencv2.4.9配置+VS2013
    我的项目配置问题及解决
    Java 8 函数式编程
    leecode刷题(17)-- 实现StrStr
    leecode刷题(16)-- 字符串转换整数
    leecode刷题(15)-- 验证回文字符串
    博客迁移通知
    leecode刷题(14)-- 有效的字母异位词
    leecode刷题(13) -- 字符串中的第一个唯一字符
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/9672882.html
Copyright © 2011-2022 走看看