[UVA]UVA1401 remember the name(Trie)

题目大意:给出一个长度为n的字符串(n<=3e5)和一个单词表(单词长度不超过100),求该字符串被这些单词表示的方案总数。

不难想到递推算法:令f[s]为表示字符串s的方案总数,若某个单词为s的前缀,f[s]=sum(f[x])(x为s去掉该单词前缀的后缀字符串)

寻找字符串的前缀是trie的经典操作,把所有单词插入trie中,然后在trie上dp即可。

PE了三次...

#include <bits/stdc++.h>

using namespace std;

typedef long long int LL;

#define st first
#define nd second
#define pb push_back
#define mp make_pair
#define pll pair <LL, LL>
#define pii pair <int, int>
#define rep(i,x) for(int i=1;i<=x;i++)

const int N = 2e6+7;
const int MX = 1e9+7;
const LL INF = 1e18+9LL;
const int mod = 20071027;

string s;

int n,cnt,l;

int mem[300010];

struct Trie{
    int val[400010],ch[400010][26];
    int sz=1;
    void init(){
        memset(ch[0],0,sizeof(ch[0]));
        sz=1;
    }
    int index(char c){return c-‘a‘;};
    void insert(char* s){
        int u=0,l=strlen(s);
        for(int i=0;i<l;i++){
            if(!ch[u][index(s[i])]){
                memset(ch[sz],0,sizeof(ch[sz]));
                val[sz]=0;
                ch[u][index(s[i])]=sz++;
            }
            u=ch[u][index(s[i])];
        }
        val[u]=1;
    }

}trie;

int solve(int st){
    if(st==l)return 1;
    if(mem[st]!=-1)return mem[st];
    int res=0;
    int u=0;
        for(int i=st;i<l;i++){
            if(trie.ch[u][trie.index(s[i])]){
                if(trie.val[trie.ch[u][trie.index(s[i])]]){
                    res+=solve(i+1),res%=mod;
                    }
                u=trie.ch[u][trie.index(s[i])];
            }
            else break;
        }
    return mem[st]=res;
}

int main(){
    while(cin>>s){
        scanf("%d",&n);
        l=s.size();
        for(int i=0;i<l;i++)mem[i]=-1;
        trie.init();
        rep(i,n){
            char a[120];
            scanf("%s",a);
            trie.insert(a);
            //trie.print(0,"");
        }

        printf("Case%d:%d\n",++cnt,solve(0));
    }
}

原文地址:https://www.cnblogs.com/xutianshu/p/10459375.html

时间: 2024-10-12 21:43:36

[UVA]UVA1401 remember the name(Trie)的相关文章

UVA 11488 Hyper Prefix Sets (Trie)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2483 Hyper Prefix Sets Prefix goodness of a set string islength of longest common prefix*number of strings in the set.For example the prefix goodnes

UVA 11732 &quot;strcmp()&quot; Anyone? (Trie)

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2832 题意:模拟strcmp()函数,给n个字符串,两两之间进行比较,问需要进行多少次比较? 解析:字符串很多,数据量大,按题意两两比较显然不现实.如果把所有的单词插入到一棵Trie里面会怎么样呢?考虑than和that对应的结点,than和that的前3个字符是一样的,但第4个

uva 1401 Remember the Word ( Trie + DP )

题意:给出n(n<=4000)个单词和一个字符串(len<=300000),求把这个字符串分解成若干个单词的拼接,有多少种方法 思路:Trie,先把单词建成Trie,然后进行dp,dp[i]表示以字符串中第i个字母为开头的情况,然后每个状态只要在Trie树上找到相应的字母开头的单词,然后dp[i] = sum{dp[i + len(x)]}进行状态转移即可 这个x是n个单词中的一个,可以用Trie查询 code: #include<cstdio> #include<cstri

UVA 11488-Hyper Prefix Sets(Trie)

题意: 给一个01串的集合,一个集合的幸运值是串的个数*集合中串的最大公共前缀 ,求所有子集中最大幸运值 分析: val[N]表示经过每个节点串的个数求幸运值 求就是每个节点值*该节点的深度 搜一遍树求出最大值 #include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cst

UVA 11732 strcmp() Anyone (Trie+链表)

先两两比较,比较次数是两者相同的最长前缀长度*2+1,比较特殊的情况是两者完全相同时候比较次数是单词长度*2+2, 两个单词'末尾\0'和'\0'比较一次,s尾部'\0'和循环内'\0'比较一次. 因此,对于一个单词,只要知道和它某个相同的最长前缀的单词数就可以计算出方案数了. 用tire,记录一颗子树上的结点数cnt[u]和在某个结点终止的单词数val[u](处理特殊情况). 因为字符集比较大,可能会有较大的空间浪费,所以用一个链式的结构保存子节点.(查找子节点的时候效率会低一些). 如果插完

LA 3942 &amp;&amp; UVa 1401 Remember the Word (Trie + DP)

题意:给你一个由s个不同单词组成的字典和一个长字符串L,让你把这个长字符串分解成若干个单词连接(单词是可以重复使用的),求有多少种.(算法入门训练指南-P209) 析:我个去,一看这不是一个DP吗?刚开始交一直是runtime error,找了好久,一直以为是数组开小了,不断增大还是这样,后来发现我用了char类型...下面分析这个题目 应该不难想到这个状态转移方程: d(i) = sum{d(i+len(x))|单词x是s[i...L]的前缀},其中len(x)是长度.d(i)表示从字符i开始

uva 1401 dp+Trie

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=&problem=4147 题意:给定一个字符串,以及若干单词,求有几种方式能用单词组成字符串 我先是dp方程推得有问题不知怎么修改搞得卡了很久,然后就是数组开得太小一直RE trie数组大小=单词个数*单词长度  dp[i]为以str[i]开头的后缀的ans,dp[i]=segma(

UVa 11732 &quot;strcmp()&quot; Anyone? (左儿子右兄弟前缀树Trie)

题意:给定strcmp函数,输入n个字符串,让你用给定的strcmp函数判断字符比较了多少次. 析:题意不理解的可以阅读原题https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2832 字符串很多,又很长,如果按照题目的意思两两比较,肯定会TLE,所以要用前缀树(Trie)来解决,当然只是用简单的前缀树也会TLE的, 我们必须对其进行优化,看了

左儿子右兄弟Trie UVA 11732 strcmp() Anyone?

UVA 11732 strcmp() Anyone?(左儿子右兄弟Trie) ACM 题目地址: UVA 11732 strcmp() Anyone? 题意: 问strcmp函数的==语句执行了几次. UVA 11732 strcmp() Anyone?(左儿子右兄弟Trie) ACM 题目地址: UVA 11732 strcmp() Anyone? 题意: 问strcmp函数的==语句执行了几次. 分析: 大白上的题目. 听说要用左儿子右兄弟的Trie,比较省空间,顺便学了下. 一边inser