Codeforces Round 70 E. You Are Given Some Strings...(AC自动机)

Portal

The meaning of problems: Given a text string T, then the string is given to N modes, two modes find any number of strings after splicing occurring in T and (may overlap)

Ideas: First, violence is not possible violence. Consider two strings can be combined enumeration point i appears on T, then the number of this position is to contribute to the answer i-terminated string multiplied by the number of strings to i + 1 is the starting position. Seeking the number of strings in each of start and end position can be AC ​​automaton. The number of forward run again AC automaton can be obtained at the end of the reverse run again the number can be calculated starting point, and then enumerate the binding site statistics to answer specific look at the code.

 

#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
struct AC_automaton
{
    int tree[maxn][30];
    int fail[maxn];
    int num[maxn];
    int tot;
    int pos[maxn];
    void Insert(char *s)
    {
        int root=0;
        for(int i = 0;s[i];++i)
        {
            int tmp=s[i]-'a';
            if(!tree[root][tmp])tree[root][tmp]=++tot;
            root=tree[root][tmp];
        }
        num[root]++;
    }
    void get_fail()
    {
        queue<int>q;
        for(int i = 0;i < 26;++i)
        if(tree[0][i])q.push(tree[0][i]);
        while(!q.empty())
        {
            int now=q.front();
            q.pop();
            num[now]+=num[fail[now]];//提前加上,匹配的时候就不用跳fail了
            for(int i = 0;i < 26;++i)
            {
                if(tree[now][i])
                fail[tree[now][i]]=tree[fail[now]][i],q.push(tree[now][i]);
                else
                tree[now][i]=tree[fail[now]][i];
            }
        }
    }
    void match(char *s)
    {
        int root=0;
        for(int i = 0;s[i];++i)
        {
            root=tree[root][s[i]-'a'];
            pos[i]=num[root];
        }
    }
}AC2,AC1;
int main()
{
    char s[maxn],a[maxn];
    scanf("%s",s);
    int n;
    scanf("%d",&n);
    for(int i = 1;i <= n;++i)
    {
        scanf("%s",a);
        AC2.Insert(a);
        reverse(a,a+strlen(a));//建立反向模式串的自动机
        AC1.Insert(a);
    }
    AC1.get_fail();
    AC2.get_fail();
    AC2.match(s);
    int ns=strlen(s);
    reverse(s,s+ns);
    AC1.match(s);
    long long ans=0;
    for(int i = 0;i < ns-1;++i)
        ans+=1ll*AC2.pos[i]*AC1.pos[ns-i-2];
    printf("%lld\n",years);
    return 0;
}

 

  

 

Guess you like

Origin www.cnblogs.com/aaddvvaanntteezz/p/11370622.html