• LA-3942(trie树+dp)


    题意:

    给出一个由多个不同单词组成的字典,和一个长字符串,把这个字符串分解成若干个单词的连接,问有多少种方法;

    思路:

    dp[i]表示s[i,L]的方案数,d[i]=∑d[j];s[i,j-1]是一个字典里的单词;

    一开始想用mp搞,最后t了;换成了trie树,由于单词的长度不超过100,所以就可以在trie树查找不超过100的长度,把出现单词结点的累加;dp[0]就是答案了;

    AC代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <bits/stdc++.h>
    #include <stack>
    
    using namespace std;
    
    #define For(i,j,n) for(int i=j;i<=n;i++)
    #define mst(ss,b) memset(ss,b,sizeof(ss));
    
    typedef  long long LL;
    
    template<class T> void read(T&num) {
        char CH; bool F=false;
        for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
        for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
        F && (num=-num);
    }
    int stk[70], tp;
    template<class T> inline void print(T p) {
        if(!p) { puts("0"); return; }
        while(p) stk[++ tp] = p%10, p/=10;
        while(tp) putchar(stk[tp--] + '0');
        putchar('
    ');
    }
    
    const LL mod=20071027;
    const double PI=acos(-1.0);
    const int inf=1e9;
    const int N=4e5+10;
    const int maxn=500+10;
    const double eps=1e-8;
    
    //map<string,int>mp;
    LL dp[N];
    char s[N],str[110];
    int sz=0;
    int ch[N][28],val[N];
    inline void Init()
    {
        mst(ch,0);
        sz=1;
        mst(val,0);
    }
    inline void insert()
    {
        int u=0,len=strlen(str);
        For(i,0,len-1)
        {
            int temp=str[i]-'a';
            if(!ch[u][temp])
            {
                //mst(ch[sz],0);
                val[sz]=0;
                ch[u][temp]=sz++;
            }
            u=ch[u][temp];
        }
        val[u]=1;
    }
    inline LL query(int l,int r)
    {
        LL ans=0;
        int u=0;
        for(int i=l;r<=r;i++)
        {
            int temp=s[i]-'a';
            if(ch[u][temp])
            {
                int x=ch[u][temp];
                if(val[x])ans=(ans+dp[i+1])%mod;
                u=x;
            }
            else break;
        }
        return ans;
    }
    int main()
    {       
            int Case=0;
            while(scanf("%s",s)!=EOF)
            {
                Init();
                printf("Case %d: ",++Case);
                int q,len=strlen(s);
                read(q);
                while(q--)
                {
                   scanf("%s",str);
                   insert();
                }
                dp[len]=1;
                for(int i=len-1;i>=0;i--)
                {
                    dp[i]=0;
                    int r=min(len-1,i+100);
                    dp[i]=query(i,r);
                }
                printf("%lld
    ",dp[0]);
            }
            
            return 0;
    }
    

      

  • 相关阅读:
    冒泡排序
    linux常用命令
    Github上将公共仓库转为私有仓库or私有仓库转为共有仓库
    使用apt更新和升级系统软件
    Django用户认证模块中继承AbstractUser与AbstractBaseUser重写User表的区别
    详解django中的collectstatic命令以及STATIC_URL、STATIC_ROOT配置
    python入门指南
    python包装不上?国内网络问题,使用豆瓣源解决
    nginx入门
    Vue 实现页面刷新(provide 和 inject)
  • 原文地址:https://www.cnblogs.com/zhangchengc919/p/5711913.html
Copyright © 2020-2023  润新知