Uva1401/LA3942 Remember the Word(trie模板)

LRJ书上例题,但是自己在思考过程中挺有收获。。。。
UVA1401题目直达
题目大意是拆解字符串,有几种方法。
简单思路:设 dp[i] 为字符串从第i位开始的拆解方法;仔细一想的话就会发现这样的关系:

dp[i]=j[1,S]dp[i+len[j]]

其中

S 为单词总数,j为单词编号。

使用trie可以实现,AC代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;
const int maxn=500000;
const int mod=20071027;

char buffer[maxn];
int dp[maxn];
int mark[maxn];
char word[5000][200];
int n;

    int val[maxn];
    int ch[maxn][27];
    int sz;
    void ini()
    {
        sz=1;
        memset(val,0,sizeof(val));
        memset(ch,0,sizeof(ch));
        memset(dp,0,sizeof(dp));
        memset(mark,0,sizeof(mark));
        memset(word,0,sizeof(word));
    }
    int ind(char c)
    {
        return c-'a';
    }


    void insert(char *s,int v)
    {
        int len=strlen(s);
        int u=0;
        for(int i=0;i<len;i++)
        {
            int num=ind(s[i]);
            if(!ch[u][num])
            {
                ch[u][num]=sz;
                sz++;
            }
            u=ch[u][num];
        }
        val[u]=v;
    }

    bool queryeach(char *s)
    {
        int parent=0;
        int len=strlen(s);
        for(int i=0;i<len;i++)
        {
            int num=ind(s[i]);
            if(ch[parent][num]==0)
            {
                return false;
            }
            parent=ch[parent][num];
        }
        return (val[parent]>0);
    }

    vector<int > query(char *s)
    {
        int parent=0;
        vector<int > ans;
        int len=strlen(s);
        for(int i=0;i<len;i++)
        {
            int num=ind(s[i]);
            if(!ch[parent][num])
            {
                break;
            }
            if(val[ch[parent][num]]!=0)
            {
                ans.push_back(val[ch[parent][num]]);
            }
            parent=ch[parent][num];

        }
        /* for(unsigned i=0;i<ans.size();i++) { printf("%d ",ans[i]); } printf("\n"); */
        return ans;
    }

char kagami[maxn];

int main()
{
    //freopen("1.out","w",stdout);
    int cas=0;
    while(~scanf("%s",buffer))
    {
        cas++;
        scanf("%d",&n);
        ini();
        int maxlen=0;
        for(int i=0;i<n;i++)
        {
            memset(kagami,0,sizeof(kagami));
            scanf("%s",kagami);
            int len=strlen(kagami);
            mark[len]++;
            maxlen=max(maxlen,len);
            strcpy(word[i],kagami);
            insert(kagami,len);
        }

        //初始化
        int len=strlen(buffer);
        for(int i=1;i<=maxlen;i++)
        {
            if(mark[i]>0)
            {
                bool flag=queryeach(buffer+len-i);
                if(flag)
                {
                    dp[len-i]=(dp[len-i]+1+mod)%mod;
                }
            }
        }
        /* for(int i=0;i<=len;i++) { printf("dp[%d]=%d\n",i,dp[i]); } printf("\n"); */
        dp[len]=0;
        for(int i=len-1;i>=0;i--)
        {
            vector<int> res=query(buffer+i);
            /* for(unsigned j=0;j<res.size();j++) { printf("res[%d]=%d\n",j,res[j]); } printf("\n"); */
            for(unsigned j=0;j<res.size();j++)
            {
                dp[i]=(dp[i]+dp[i+res[j]]+mod)%mod;
            }
        }
        /* for(int i=0;i<=len;i++) { printf("dp[%d]=%d\n",i,dp[i]); } */
        printf("Case %d: %d\n",cas,(dp[0]+mod)%mod);
    }
    return 0;
}

调了一段时间,不过收获还是比较大的。

点赞