AC自动机处理多串匹配——cf1202E

Posted zsben991126

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AC自动机处理多串匹配——cf1202E相关的知识,希望对你有一定的参考价值。

si+sj中间有一个切割点,我们在t上枚举这个切割点i,即以t[i]作为最后一个字符时求有多少si可以匹配,以t[i+1]作为第一个字符时有多少sj可以匹配

那么对s串正着建一个ac自动机,反着建一个自动机,然后t正反各匹配一次,用sum[]数组记录t[i]作为最后一个字符可以匹配的串数量

注意:求sum数组时,暴力跳fail显然会t,考虑到跳fail是为了统计匹配串的后缀,那么我们在build时,就可以在处理fail指针时就可以把那个fail的end加到now的end上去,这样就避免了暴力跳fail

#include<bits/stdc++.h>
using namespace std;
#define N 200005

struct Trie
    int nxt[N][26],fail[N],end[N];
    int root,L;
    int newnode()
        memset(nxt[L],-1,sizeof nxt[L]);
        end[L]=0;
        return L++;
    
    void init()
        L++;
        root=newnode();
    
    void insert(char buf[])
        int len=strlen(buf+1);
        int now=root;
        for(int i=1;i<=len;i++)
            if(nxt[now][buf[i]-a]==-1)
                nxt[now][buf[i]-a]=newnode();
            now=nxt[now][buf[i]-a];
        
        end[now]++;
    
    void build()
        queue<int>q;
        fail[root]=root;
        for(int i=0;i<26;i++)
            if(nxt[root][i]==-1)
                nxt[root][i]=root;
            else 
                fail[nxt[root][i]]=root;
                q.push(nxt[root][i]);
            
        while(q.size())
            int now=q.front();
            q.pop(); 
            for(int i=0;i<26;i++)
                if(nxt[now][i]==-1)
                    nxt[now][i]=nxt[fail[now]][i];
                else 
                    fail[nxt[now][i]]=nxt[fail[now]][i];
                    end[nxt[now][i]]+=end[nxt[fail[now]][i]];
                    q.push(nxt[now][i]);
                
        
    
    int sum[N];
    int query(char buf[])
        int len=strlen(buf+1);
        int now=root;
        for(int i=1;i<=len;i++)
            now=nxt[now][buf[i]-a];
            sum[i]+=end[now];
        
    
; 

char buf[N],t[N];
Trie t1,t2;
int n;
void reserve(char s[])
    int i=1,j=strlen(s+1);
    while(i<j)
        swap(s[i],s[j]);
        ++i,--j;
    


int main()
    t1.init();
    t2.init();    
    scanf("%s%d",t+1,&n);
    for(int i=1;i<=n;i++)
        scanf("%s",buf+1);
        t1.insert(buf);
        reserve(buf);
        t2.insert(buf);
    
    t1.build();
    t2.build();
    t1.query(t);
    reserve(t);
    t2.query(t);
    
    int len=strlen(t+1);
    long long ans=0;
    for(int i=0;i<len;i++)
        ans+=(long long)t1.sum[i]*t2.sum[len-i];
    cout<<ans<<\n;

 

以上是关于AC自动机处理多串匹配——cf1202E的主要内容,如果未能解决你的问题,请参考以下文章

AC自动机总结

bzoj2553

hdu 2222 Keywords Search(ac自动机)

[CF1038F]Wrap Around[AC自动机+dp]

[BZOJ1559][JSOI2009]密码(AC自动机)

HDU 5069 Harry And Biological Teacher(AC自动机+线段树)