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

  

原文地址:https://www.cnblogs.com/zhangchengc919/p/5711913.html