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]);
}