zoukankan      html  css  js  c++  java
  • 题解 UVA1401 【Remember the Word】

    题目链接:Link

    Solution

    第一次写Trie,写篇题解纪念一下......

    令d(i)表示从字符i开始的字符串(即后缀 S[i...L-1])的分解方案数,则d(i)=sum{d(i+len(x)) | 单词x是 S[i...L-1]的前缀}。

    显然,关键点就在判断前缀上。可以把所有的单词组织成Trie,然后试着在Trie中查找S[i...L-1],每找到一个单词节点,就状态转移一次....

    #include<cstdio>
    #include<cstring>
    const int mod=20071027;
    const int maxL=300000;
    int L,S,d[maxL+5],kase;
    char str[maxL+5],tmp[105];
    const int maxnode=4000*105;//注意开大一点
    const int sigma_size=26;
    struct Trie
    {
    	int ch[maxnode][sigma_size];
    	bool val[maxnode];
    	int sz;
    	Trie() { sz=1; }
    	inline void clear()
    	{
    		sz=1;
    		memset(ch,0,sizeof(ch));
    		memset(val,0,sizeof(val));//一次性赋值
    	}
    	inline void insert(char *s)
    	{
    		int u=0,n=strlen(s);
    		for(int i=0;i<n;i++)
    		{
    			int c=s[i]-'a';
    			if(!ch[u][c])
    				ch[u][c]=sz++;//申请新节点
    			u=ch[u][c];
    		}
    		val[u]=1;
    	}
    }trie;
    int main()
    {
    #ifdef local
    	freopen("pro.in","r",stdin);
    #endif
    	while(scanf("%s",str)==1)
    	{
    		L=strlen(str);
    		scanf("%d",&S);
    		memset(d,0,sizeof(d));
    		trie.clear();
    		for(int i=0;i<S;i++)
    		{
    			scanf("%s",tmp);
    			trie.insert(tmp);
    		}
    		d[L]=1;//边界
    		for(int i=L-1;i>=0;i--)
    			for(int j=0,u=0;i+j<L&&trie.ch[u][str[i+j]-'a'];j++)
    			{
    				u=trie.ch[u][str[i+j]-'a'];
    				if(trie.val[u]) d[i]=(d[i]+d[i+j+1])%mod;
                    //状态转移
    			}
    		printf("Case %d: %d
    ",++kase,d[0]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Codeforces Round #425 (Div. 2) Problem A Sasha and Sticks (Codeforces 832A)
    bzoj 2301 Problem b
    bzoj 1101 [POI2007]Zap
    bzoj 2005 能量采集
    bzoj 2527 Meteors
    bzoj 2724 [Violet 6]蒲公英
    回顾树状数组
    bzoj 3237 连通图
    bzoj 2733 永无乡
    Codeforces 817C Really Big Numbers
  • 原文地址:https://www.cnblogs.com/happyZYM/p/11380110.html
Copyright © 2011-2022 走看看