UVA 3942 Remember the Word(Trie树)

来源:互联网 发布:360软件大全官方下载 编辑:程序博客网 时间:2024/05/28 23:11

题目链接

题目大意:给出一个由s个不同的单词组成的字典和一个长的字符串。把这个字符串分解成若干个单词的连接(单词可以重复使用),有多少种方法?比如,有4个单词a, b, cd, ab,则abcd可以有两种分解的方法:a+b+cd 和 ab+cd。

  第一次接触Trie树,有些不是很理解,暂时记录下来 ,作为一个模板。


//Trie树+dp#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>using namespace std;#define maxnode 4000*100+100#define sigma_size 26#define mod 20071027char s[300100];int dp[300110];struct Trie{    int ch[maxnode][sigma_size];    int val[maxnode];    int sz;//节点总数    void init(){sz=1; memset(ch[0],0,sizeof(ch[0])); val[0]=0;}    int idx(char c) { return c-'a'; }    void insert(char *s,int v)    {        int u=0,n=strlen(s);        for(int i=0;i<n;i++)        {            int c=idx(s[i]);            if(!ch[u][c])  //节点不存在,开辟一段空间            {                memset(ch[sz],0,sizeof(ch[sz]));                val[sz]=0; //中间节点的附加信息为0                ch[u][c]=sz++;//新建节点            }            u=ch[u][c]; //往下走        }        val[u]=n;//表示这个节点结束了,看题意要求取值    }    void find(char *s,int st,int l)    {        int u=0;        for(int i=0;i<l;i++)        {            int c=idx(s[i]);            if(!ch[u][c]) return ;            u=ch[u][c];            if(val[u]) dp[st]=(dp[st]+dp[st+val[u]])%mod;        }        return ;    }};Trie word;int main(){   // printf("%d**\n",maxnode);    int cas=1;    while(~scanf("%s",s))    {        memset(dp,0,sizeof(dp));        word.init();        int len=strlen(s);        int n;        scanf("%d",&n);        char c[110];        for(int i=0;i<n;i++)        {            scanf("%s",c);            word.insert(c,1);        }        dp[len]=1;        for(int i=len-1;i>=0;i--)        {            word.find(s+i,i,len-i);        }        printf("Case %d: %d\n",cas++,dp[0]%mod);    }    return 0;}

1 0