[JSOI2007]文本生成器 AC自动机

https://www.luogu.org/problemnew/show/P4052

https://ac.nowcoder.com/acm/problem/20155

中文题,相信大家都读得懂;

首先要求出现过的串的总数,就用总数,减去,没有出现过的,既然是几个串,那就是AC自动机,加矩阵快速幂,但不过这道题由于文本比较长所以就只有用dp刚刚开始想着用类似的数位dp的办法做,只能过一半的样列,后来暴力写,也只能过一半,最后发现fail没有更新下去。改了后,前面的类似数位dp 的还是没有过,后面的倒是过了,可能想错了吧。

dp[m][i]表示取了m位,第m位i的方法。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=10007;
const int N=6000+10;
struct Aho_Trie
{
    int nxt[N][26],fail[N],endd[N];
    int l,root;
    int newnode()
    {
        endd[l]=fail[l]=0;
        memset(nxt[l],0,sizeof(nxt[l]));
        return l++;
    }
    void init()
    {
        l=0;
        root=newnode();
    }
    void Insert(char *s)
    {
        int len=strlen(s),u=root;
        for(int i=0;i<len;i++)
        {
            int x=s[i]-'A';
            if(nxt[u][x]==0) nxt[u][x]=newnode();
            u=nxt[u][x];
        }
        endd[u]=1;
    }
    void build()
    {
        queue<int>qu;
        for(int i=0;i<26;i++)
            if(nxt[root][i]!=0) qu.push(nxt[root][i]);
        while(!qu.empty())
        {
            int u=qu.front();qu.pop();
            endd[u]+=endd[fail[u]];
            for(int i=0;i<26;i++)
            {
                if(nxt[u][i]) fail[nxt[u][i]]=nxt[fail[u]][i],qu.push(nxt[u][i]);
                else nxt[u][i]=nxt[fail[u]][i];
            }
        }
    }
}ac;
int n,m,dp[110][N];
char tmp[110];

int quick(int a,int n)
{
    int ans=1;
    while(n)
    {
        if(n&1)
            ans=ans*a%mod;
        a=a*a%mod;
        n>>=1;
    }
    return ans;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>m;
    ac.init();
    for(int i=1;i<=n;i++)
    {
        cin>>tmp;
        ac.Insert(tmp);
    }
    ac.build();
    int cnt=ac.l-1;
    ///cout<<cnt<<endl;
    memset(dp,0,sizeof(dp));
    dp[0][0]=1;
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<=cnt;j++)
        {
            for(int k=0;k<26;k++)
            {
                if(!ac.endd[ac.nxt[j][k]])
                    dp[i+1][ac.nxt[j][k]]=(dp[i+1][ac.nxt[j][k]]+dp[i][j])%mod;
            }
        }
    }
    int ans=quick(26,m);
    for(int i=0;i<=cnt;i++)
    {
        ans=(ans-dp[m][i]+mod)%mod;
        ///cout<<dp[m][i]<<endl;
    }
    cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/KXL5180/article/details/89642211
今日推荐