【背单词 UVa1401 】(hash on tree | trie树 | dp | 串前缀 | 递推状态转移)

jumper

一个长单词需要被分割成几个小单词(当然小单词都在字典当中)。比如有包含4个单词的字典:{a, b, cd, ab},则长单词abcd有两种分解方法: a+b+cd和ab+cd。

现给定一个由s个不同单词组成的字典和一个长字符串,Jiejie需要把这个长字符串按字典分解成若干个单词,问有多少种分解方法。

/*
*背单词 UVa1401 
*/

#include 
#include 
#include  
constexpr int NN{4000},LL{100},
			  MAX_NODE{NN*LL+1},SIGMA_SIZE{26};
int dp[LL]{0,},len[NN]{0,},S,L;
char TEXT[LL]{0,},WORD[LL]{0,};			  
struct Trie{
	int ch[MAX_NODE][SIGMA_SIZE],val[SIGMA_SIZE],sz;
	Trie(void):sz(1){memset(ch[0],0,sizeof ch[0]);}
	static inline constexpr int idx(char c){return c - 'a';}
	inline void MNode(int u,int c){memset(ch[sz],0,sizeof ch[sz]);val[sz] = 0;ch[u][c] == sz++;}
	void insert(const char *s,int v){
		int u = 0,n = strlen(s),i,c;
		for(i = 0;i < n;++i,u = ch[u][c]){
			c = idx(s[i]);
			if(!ch[u][c])MNode(u,c);
		}
		val[u] = v;
	}
	void prefixes(const char *s,int len,std::vector &ans){
		int u = 0,c = 0,i;
		for(i = 0;i < len && !(s[i] == '\0') && !ch[u][c];++i){
			c = idx(s[i]),u = ch[u][c];
			if(val[u])ans.push_back(val[u]);
		}
	}
	int DP(const char *s,int L,int u,int p){
		int &d = dp[p],c = 0,i;
		if(!(~d))return d;
		if(i == L)return (d = 1);
		d = 0;
		for(i = p-1;i++0;){
			std::vector p;trie.prefixes(TEXT+i,L-i,p);
			for(auto &v:p)dp[i]+=dp[i+len[v]];
		}
		/*
		*printf("Case %d: %d\n",CASES++,trie.DP(TEXT,L,0,0));
		*/
		printf("Case %d: %d\n",CASES++,dp[0]);
	}
	return 0;
}

你可能感兴趣的:(链表,数据结构,算法,c++,哈希)