zoukankan      html  css  js  c++  java
  • [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
    ",++cnt,solve(0));
        }
    }
  • 相关阅读:
    nodeJS入门01-http模块
    nodeJS入门-Buffer对象
    php与MySQL(php内置mysql函数)
    php与MySQL(基本操作)
    log4net
    js验证小数类型(浮点数)和整数类型
    牛腩学ASP.NET CORE做博客视频
    opencv再学习之路(八)---设定感兴趣区域(RIO)
    opencv再学习之路(四)---色彩分割得到二值图像
    opencv再学习之路(三)---形态学操作
  • 原文地址:https://www.cnblogs.com/xutianshu/p/10459375.html
Copyright © 2011-2022 走看看