P1666 前缀单词

P1666 前缀单词


tire树上跑dp

首先将trie树建出来,然后对于每个节点。考虑他的子节点。
子节点的方案数都互不干扰,所以子节点与其他子节点的的方案数可以利用乘法原理算出来。
然后如果这个节点是一个字符串的结尾。那么这个字符串可以单独作为一个集合。然后方案数+1.
如若无子节点,则这个节点是trie树中的叶子节点。那么有两种方案,选与不选。

然后如此做一个树形dp就可以了。

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
const int maxn=3000;
const int N=27;
int T[maxn*N][N],tail;
long long End[maxn*N],F[maxn*N];
char Data[maxn];
void insert(char *A,int len)
{
    int now=0;
    for(int i=1;i<=len;i++)
    {
        int nxt=A[i]-'a';
        if(!T[now][nxt])    T[now][nxt]=++tail;
        now=T[now][nxt];
    }
    End[now]++;
}
void dfs(int now)
{
    F[now]=1ll;
    for(int i=0;i<26;i++)
    {
        if(!T[now][i])  continue;
        dfs(T[now][i]);
        F[now]*=F[T[now][i]];
    }
    F[now]+=End[now];
    return ;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",Data+1);
        insert(Data,strlen(Data+1));
    }
    dfs(0);
    printf("%lld",F[0]);
}

猜你喜欢

转载自www.cnblogs.com/Lance1ot/p/9785691.html