[String] Several AC automata above BZOJ find the question with the most number of occurrences of the string

【BZOJ3172: word】

topic:

         Someone reads a paper, and a paper is made up of many (N) words. But he found that a word appears many times in the paper, and now wants to know how many times each word appears in the paper. N<=200, the total word length does not exceed 10^6.

Ideas:

        Simple question, establish an AC automaton, each position is ++ when inserted, which represents the number of strings suffixed with the current position for accumulation during fail transfer. Then build gets the fail pointer; finally it accumulates from the leaves to the root.

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000010;
char c[maxn]; int ans[maxn],pos[210],N;
struct Trie
{
    int ch[maxn][26],cnt,times,fail[maxn],q[maxn],head,tail;
    Trie(){ cnt=times=head=tail=0; }
    int insert(){
        int Now=0,L=strlen(c+1);
        for(int i=1;i<=L;i++){
            if(!ch[Now][c[i]-'a']) ch[Now][c[i]-'a']=++cnt;
            Now=ch[Now][c[i]-'a'];
            ans[Now]++;
        }
        return Now;
    }
    void build()
    {
        for(int i=0;i<26;i++)
          if(ch[0][i]) q[++head]=ch[0][i];
        while(tail<head){
            int Now=q[++tail];
            for(int i=0;i<26;i++){
                if(ch[Now][i]){
                    fail[ch[Now][i]]=ch[fail[Now]][i];
                    q[++head]=ch[Now][i];
                }
                else ch[Now][i]=ch[fail[Now]][i];
            }        
        }
        for(int i=tail;i>=1;i--) ans[fail[q[i]]]+=ans[q[i]];
    }
}T;
intmain ()
{
    scanf("%d",&N);
    for(int i=1;i<=N;i++){
        scanf("%s",c+1);
        pos[i]=T.insert();
    }
    T.build();
    for(int i=1;i<=N;i++) printf("%d\n",ans[pos[i]]);
    return 0;
}
View Code

 

[BZOJ2434 Ali's Typewriter]:

topic:

          Given N strings. Now there are Q questions, each time the question is given (i, j), find the number of occurrences of the i-th string in the j-th string. 1<=N<=10e5; 1<=M<=10e5; input total length<=10e5

Ideas:

         I thought that the previous question was a word interrogation, and it was an overall search, so one topology accumulation was enough, but this question was asked multiple times, and it was for the number of inclusions between the two strings represented on the Trie tree, and the overall method could not be used.

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325689498&siteId=291194637