字典树初体验

计算机科学中,trie,又称前缀树字典树,是一种有序,用于保存关联数组,其中的键通常是字符串。与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。一般情况下,不是所有的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相关的值。

此题是典型的dp思想运用dp数组进行递推

暂且传上代码当作字典树模板

简单记录一下字典树原理

用ch二维数组记录作为路径记录数组 end作为标记数组判断当前字母是否为结尾

写插入函数及查找函数即可

典型例题为判断前缀

附上

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
const int maxm=400005;
const int mod=20071027;
char s[300005];
int dp[300005];
char temp[105];
int ch[maxm][30];
bool en[maxm];
int tot;
int len;
void inser()
{
    int lent=strlen(temp);
    int u=1;
    for(int i=0;i<lent;i++)
    {
        if(!ch[u][temp[i]-'a'])
            ch[u][temp[i]-'a']=++tot;
        u=ch[u][temp[i]-'a'];
        if(i==lent-1)
            en[u]=true;
    }
}
void fin(int x)
{
    int tmp=dp[x-1];
    int u=1;
    while(1)
    {
        if(!ch[u][s[x]-'a'])
            break;
        u=ch[u][s[x]-'a'];
        if(en[u]==true)
            dp[x]=(dp[x]+tmp)%mod;
        x++;
    }
}
int main()
{
    int cas=0;
    while(~scanf("%s",s+1))
    {
        cas++;
        tot=1;
        memset(dp,0,sizeof(dp));
        memset(ch,0,sizeof(ch));
        memset(en,false,sizeof(en));
        int q;
        scanf("%d",&q);
        while(q--)
        {
            scanf("%s",temp);
            inser();
        }
        len=strlen(s+1);
        dp[0]=1;
        for(int i=1;i<=len;i++)
        {
            if(dp[i-1])
                fin(i);
        }
        printf("Case %d: %d\n",cas,dp[len]);
    }
}