zoukankan      html  css  js  c++  java
  • bzoj3172: [Tjoi2013]单词

    AC自动机.

    统计每个字符串在自己和其他字符串中出现的次数。

    ac自动机的概念,首先有个trie树保存了所有的字符串。

    fail指针指向该字符串的后缀在整个trie树中可以做最长的前缀的位置。

    每个字符串都可以由fail指针转移到是该字符串字串的位置。

    所以很多统计就可以进行辣。

    字符串的题好难。。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn = 1000000 + 10;
    
    struct AC {
        int a[maxn][26],sum[maxn],q[maxn],fail[maxn]; 
        int cnt,l,r,p;
        char s[maxn];
        void insert(int &p) {
            scanf("%s",s);
            int len=strlen(s);    
            p=1;
            for(int i=0;i<len;i++) {
                int c=s[i]-'a';
                if(!a[p][c]) a[p][c]=++cnt;
                p=a[p][c];
                sum[p]++;
            }
        }
        
        void get_fail() {
            l=r=0;
            fail[1]=0;
            q[r++]=1;
            while(l<r) {
                p=q[l++];
                for(int i=0;i<26;i++) 
                    if(a[p][i]) {
                        int k=fail[p];
                        while(!a[k][i]) k=fail[k];
                        fail[a[p][i]]=a[k][i];    
                        q[r++]=a[p][i];
                    }
            }
            for(int i=r-1;i>=0;i--) 
                sum[fail[q[i]]]+=sum[q[i]];
        }
        
        AC() {
            cnt=1;
            for(int i=0;i<26;i++) a[0][i]=1;        
        }
    }am;
    
    int pos[maxn];
    int n;
    
    int main() {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) am.insert(pos[i]); 
        am.get_fail();
        for(int i=1;i<=n;i++) printf("%d
    ",am.sum[pos[i]]);
        return 0;    
    }
  • 相关阅读:
    python解析网页
    node.js 爬虫
    c++ split实现
    foldl foldr
    爬虫http header gzip
    命令[10]
    命令[08]
    命令[15]
    命令[13]
    命令[11]
  • 原文地址:https://www.cnblogs.com/invoid/p/5631708.html
Copyright © 2011-2022 走看看