• UVA 3942 Remember the Word (Trie+DP)题解


    思路:

    大白里Trie的例题,开篇就是一句很容易推出....orz

    这里需要Trie+DP解决。

    仔细想想我们可以得到dp[i]=sum(dp[i+len[x]])。

    这里需要解释一下:dp是从最后一个字母往前dp,dp[i]代表从i这个字符开始到最后一个字符的这个字符串(就是s[i,i+1,...,L])所能拆分的个数,所以我们每次查询s[i,i+1,...,k]是否存在这个前缀,都的话就加上dp[k+1],最后答案是dp[0]。注意dp[L+1]应该初始化为1,因为整个s[i,i+1,...,L]都是前缀就要+1种拆分方法。

    这里Trie用的大白模板,自己写的一直超时也不知道为什么,把大白模板的结构体去掉也超时emmm,求大神讲解

    5.15更新:今天一直尝试终于知道为什么超时了,因为之前每次query()都会计算一次s的长度,如果s很长,询问也很多,那么在strlen()上就会费很多时间(居然是这个原因orz),现在附上我自己的指针版


    第二次代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<queue>
    #include<cmath>
    #include<string>
    #include<stack> 
    #include<set>
    #include<map>
    #include<vector>
    #include<iostream>
    #include<algorithm>
    #include<sstream>
    #define ll long long
    const int N=300005;
    const int MOD=20071027;
    using namespace std;
    char s[N];
    int dp[N];
    struct Trie{
    	Trie *next[26];
    	int num;
    	Trie(){
    		num=0;
    		for(int i=0;i<26;i++){
    			next[i]=NULL;
    		}
    	}
    };
    Trie *root;
    void insert(char a[]){
    	int len=strlen(a);
    	Trie *p=root;
    	for(int i=0;i<len;i++){
    		int v=a[i]-'a';
    		if(p->next[v]==NULL) p->next[v]=new Trie();
    		p=p->next[v];
    	}
    	p->num=1;
    }
    int query(char a[],int head,int len){
    	Trie *p=root;
    	int res=0;
    	for(int i=head;i<len;i++){
    		int v=a[i]-'a';
    		if(!p->next[v]) return res;
    		p=p->next[v];
    		if(p->num){
    			res+=dp[i+1];
    			res%=MOD;
    		}
    	}
    	return res;
    }
    void del(Trie *p){
    	if(p==NULL) return;
    	for(int i=0;i<26;i++){
    		if(p->next[i]) del(p->next[i]);
    	}
    	delete p;
    }
    int main(){
    	char a[105];
    	int num;
    	int k=1;
    	while(~scanf("%s",s)){
    		root=new Trie();
    		scanf("%d",&num);
    		for(int i=0;i<num;i++){
    			scanf("%s",a);
    			insert(a);
    		}
    		int len=strlen(s);
    		dp[len]=1;
    		for(int i=len-1;i>=0;i--){
    			dp[i]=query(s,i,len);	//这里一定要直接传入len,不然重新算会超时 
    		}
    		printf("Case %d: %d
    ",k++,dp[0]);
    		del(root);
    	}
        return 0;  
    }  
    

    第一次代码(数组版):

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<queue>
    #include<cmath>
    #include<string>
    #include<stack> 
    #include<set>
    #include<map>
    #include<vector>
    #include<iostream>
    #include<algorithm>
    #include<sstream>
    #define ll long long
    const int N=300005;
    const int MOD=20071027;
    using namespace std;
    char s[N];
    int dp[N];
    struct Trie
    {  
        int ch[4*N][26];  
        int val[4*N];  
        int sz;  
        void reset(){memset(ch[0],0,sizeof ch[0]);memset(val,0,sizeof val);sz=1;} 
      
        int idx(char c){return c-'a';}  
        void insert(char *s)  
        {  
            int u=0,l=strlen(s);  
            for(int i=0;i<l;++i){  
                int c=idx(s[i]);  
                if(!ch[u][c]){  
                    memset(ch[sz],0,sizeof ch[sz]);  
                    ch[u][c]=sz++;  
                }  
                u=ch[u][c];  
            }  
            val[u]=1;  
        }  
      
        int query(char *s,int p)  
        {  
            int u=0,l=strlen(s),res=0;  
            for(int i=p;i<l;++i){  
                int c=idx(s[i]);  
                if(!ch[u][c]) return res;  
                u=ch[u][c];  
                if(val[u]){  
                    res+=dp[i+1];  
                    res%=MOD;  
                }  
            }  
            return res;  
        }
    }T;  
    
    int main(){
    	char a[105];
    	int num;
    	int k=1;
    	while(~scanf("%s",s)){
    		T.reset();
    		memset(dp,0,sizeof(dp)); 
    		scanf("%d",&num);
    		for(int i=0;i<num;i++){
    			scanf("%s",a);
    			T.insert(a);
    		}
    		int len=strlen(s);
    		dp[len]=1;
    		for(int i=len-1;i>=0;i--){
    			dp[i]=T.query(s,i);
    		}
    		printf("Case %d: %d
    ",k++,dp[0]);
    	}
        return 0;  
    }  
    

  • 相关阅读:
    早晨突然想到的几句话
    VBA-工程-找不到工程或库-解决方案
    Mysql 服务无法启动 服务没有报告任何错误
    一道有趣的面试题
    异步和多线程
    异或运算
    线性代数解惑
    全文搜索引擎 Elasticsearch (一)
    HandlerExceptionResolver统一异常处理 返回JSON 和 ModelAndView
    MySQL 20个经典面试题
  • 原文地址:https://www.cnblogs.com/KirinSB/p/9409091.html
Copyright © 2020-2023  润新知