La 3942 字符串+dp

题目大意:一个字符串,可以分解成若干英语单词的连接(单词可以重复使用),求有多少种方法?

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

const int maxl=300005;
const int maxwn=4005;
const int maxwl=105;
const int MOD=20071027;
const int maxnode=400005;
const int sigma_size=26;

struct Trie
{
    int ch[maxnode][sigma_size];
    int val[maxnode];
    int sz;
    void clear(){sz=1;memset(ch[0],0,sizeof(ch[0]));}
    int idx(char c){ return c-'a'; }
    void insert(const char *s,int v)
    {
        int i,c,u=0,n=strlen(s);
        for(i=0;i<n;i++)
        {    
            c=idx(s[i]);
            if(!ch[u][c])
            {
                memset(ch[sz],0,sizeof(ch[sz]));
                val[sz]=0;
                ch[u][c]=sz++;
            }
            u=ch[u][c];
        }
        val[u]=v;
    }
    void find_prefixes(const char *s,int len,vector<int> &ans)
    {
        int i,c,u=0;
        for(i=0;i<len;i++)
        {
            if(s[i]=='') break;
            c=idx(s[i]);
            if(!ch[u][c]) break;
            u=ch[u][c];
            if(val[u]) ans.push_back(val[u]);
        }
    }
}trie;

int d[maxl],len[maxwn],S;
char text[maxl],word[maxwl];
int main()
{
    int icase=1,i,j,L;
    while(scanf("%s %d",text,&S) == 2)
    {
        trie.clear();
        for(i=1;i<=S;i++)
        {
            scanf("%s",word);
            len[i]=strlen(word);
            trie.insert(word,i);
        }
        memset(d,0,sizeof(d));
        L=strlen(text);
        d[L]=1;
        for(i=L-1;i>=0;i--)
        {
            vector<int> p;
            trie.find_prefixes(text+i,L-i,p);
            for(j=0;j<p.size();j++)
                d[i]=(d[i]+d[i+len[p[j]]])%MOD;
        }
        printf("Case %d: %d
",icase++,d[0]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/xiong-/p/3608692.html