UVALive 3942 - Remember the Word(DP,数组Trie+指针Trie)

UVALive 3942 - Remember the Word(DP,数组Trie+指针Trie)

ACM

题目地址:

UVALive 3942 - Remember the Word

题意:

给一些单词,然后给一个长的单词,问有几种方法能组成这个大单词,单词可以重复用。

分析:

DP[i]=sum{DP[j} (i<j<len),从后往前求。

本来用数组Trie写得爽爽的,1A了。

发现2s多,不能忍!

然后用指针Trie写了一遍,各种出错,整个人都不好了...

研究了一遍别人代码,发现快的都是没写成一个struct的,无语。

代码:

(数组Trie)

/*
*  Author:      illuz <iilluzen[at]gmail.com>
*  File:        UVALive3942.cpp
*  Create Date: 2014-09-23 15:43:26
*  Descripton:  trie
*/

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define repf(i,a,b) for(int i=(a);i<=(b);i++)
typedef long long ll;

const int N = 300010;
const int MAXNODE = 400010;
const int MAXSON = 26;
const int MOD = 20071027;

char st[N], wd[110];
int cas, n;
int d[N];

// array index
struct ATrie {
	int ch[MAXNODE][MAXSON];
	int val[MAXNODE];
	int sz;		// num of nodes
	ATrie() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); }
	void init() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); }
	inline int idx(char c) { return c - 'a'; }

	void insert(char *s, int v = 1) {
		int u = 0, len = strlen(s);
		repf (i, 0, len - 1) {
			int c = idx(s[i]);
			if (!ch[u][c]) {
				memset(ch[sz], 0, sizeof(ch[sz]));
				val[sz] = 0;
				ch[u][c] = sz++;
			}
			u = ch[u][c];
		}
		val[u] = v;
	}

	// if s in trie return the value, else return 0
	int find(char *s, int pos) {
		int u = 0, len = strlen(s), cnt = 0;
		repf (i, 0, len) {
			int c = idx(s[i]);
			if (val[u])
				cnt = (cnt + d[pos + i]) % MOD;

			if (ch[u][c])
				u = ch[u][c];
			else
				return cnt;
		}
	}
} trie;

int main() {
	// ios_base::sync_with_stdio(0);
	cas = 1;
	while (~scanf("%s", st)) {
		trie.init();
		scanf("%d", &n);
		repf (i, 0, n - 1) {
			scanf("%s", wd);
			trie.insert(wd);
		}

		int len = strlen(st);
		d[len] = 1;
		for (int i = len - 1; i >= 0; i--) {
			d[i] = trie.find(st + i, i);
		}
		printf("Case %d: %d\n", cas++, d[0]);
	}
}

(指针Trie)

/*
*  Author:      illuz <iilluzen[at]gmail.com>
*  File:        UVALive3942_pointer_trie.cpp
*  Create Date: 2014-09-23 16:24:32
*  Descripton:  pointer trie
*/

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define repf(i,a,b) for(int i=(a);i<=(b);i++)
typedef long long ll;

const int N = 300010;
const int MAXSON = 26;
const int MOD = 20071027;

char st[N], wd[110];
int cas, n;
int d[N];

// pointer trie
struct Node {
	int val;
	Node *next[MAXSON];
};

struct PTrie {
	Node *root;
	PTrie() { root = newNode(); }
	void init() { del(root); root = newNode(); }
	inline int idx(char c) { return c - 'a'; }

	Node *newNode() {
		Node *u = new Node;
		repf (i, 0, MAXSON - 1) {
			u->next[i] = NULL;
		}
		u->val = 0;
		return u;
	}

	void insert(char *s, int v = 1) {
		Node *u = root;
		int len = strlen(s);
		repf (i, 0, len - 1) {
			int c = idx(s[i]);
			if (u->next[c] == NULL) {
				u->next[c] = newNode();
			}
			u = u->next[c];
		}
		u->val = v;
	}

	int find(char *s, int pos) {
		Node*u = root;
		int len = strlen(s), cnt = 0;
		repf (i, 0, len) {		// remember to len
			if (u->val)
				cnt = (cnt + d[pos + i]) % MOD;
			if (i == len)		// prevent to voer the string
				return cnt;
			int c = idx(s[i]);
			if (u->next[c] == NULL)
				return cnt;
			u = u->next[c];
		}
	}

	void del(Node *rt) {
		if (rt == NULL)
			return;
		else {
			repf (i, 0, MAXSON - 1)
				if (rt->next[i] != NULL)
					del(rt->next[i]);
		}
		delete rt;
	}
} trie;

int main() {
	// ios_base::sync_with_stdio(0);
	cas = 1;
	while (~scanf("%s", st)) {
		scanf("%d", &n);
		repf (i, 0, n - 1) {
			scanf("%s", wd);
			trie.insert(wd);
		}

		int len = strlen(st);
		d[len] = 1;
		int i = len - 1;
		while (i >= 0) {
			d[i] = trie.find(st + i, i);
			i--;
		}
		printf("Case %d: %d\n", cas++, d[0]);
		trie.init();
	}
}
时间: 2024-10-09 01:46:23

UVALive 3942 - Remember the Word(DP,数组Trie+指针Trie)的相关文章

UVaLive 3942 Remember the Word (dp+字典树)

Remember the Word DescriptionNeal is very curious about combinatorial problems, and now here comes a problem about words. Knowing that Ray has a photographic memory and this may not trouble him, Neal gives it to Jiejie. Since Jiejie can’t remember nu

UVALive - 3942 Remember the Word[Trie DP]

UVALive - 3942 Remember the Word Neal is very curious about combinatorial problems, and now here comes a problem about words. Know- ing that Ray has a photographic memory and this may not trouble him, Neal gives it to Jiejie. Since Jiejie can’t remem

UVALive 3942 Remember the Word 字典树+dp

/** 题目:UVALive 3942 Remember the Word 链接:https://vjudge.net/problem/UVALive-3942 题意:给定一个字符串(长度最多3e5)和m个单词(每个单词长度最多100).单词都是不同的.该字符串可以由若干个单词组成,问最多有多少种组合方式. 思路:字典树+dp 用字典树处理好m个单词,定义dp[i]表示从i开始的字符串可以由单词组成的方式数. 那么dp[i] += dp[i+j]; j表示某个单词和字符串的[i,i+j-1]匹配

UVALive - 3942 - Remember the Word (Trie树)

UVALive - 3942 Remember the Word Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Neal is very curious about combinatorial problems, and now here comes a problem about words. Knowing that Ray has a p

UVALive - 3942 Remember the Word[树状数组]

UVALive - 3942 Remember the Word A potentiometer, or potmeter for short, is an electronic device with a variable electric resistance. It has two terminals and some kind of control mechanism (often a dial, a wheel or a slide) with which the resistance

【暑假】[实用数据结构]UVAlive 3942 Remember the Word

UVAlive 3942 Remember the Word 题目: Remember the Word Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Neal is very curious about combinatorial problems, and now here comes a problem about words. Know

(trie)UVALive - 3942 Remember the Word

题目链接 设d[i]表示从下标i的字符开始的字符串的分解方法数,显然有倒序的递推公式. 需要求每个位置开始是否能组成模式串的前缀,才可以建立正确的递推. 1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 #include <qu

UVALive 3942 Remember the Word

空降链接:https://vjudge.net/problem/UVALive-3942 题意: 给出一个字符串s(strlen(s)<=3e5)和一堆字符串str[MAX](MAX<=4000,strlen(str[i])<=100),每个str[i]可以用无限次,求用str这些字符串拼接成s的方案数. 题解: 根据题意肯定要先建棵trie...然后开始xjbDP了.因为每个串的长度都<=100,所以每次可以枚举s的下标i作为起始坐标,在字典树中找当前下标为起点的前缀,如果在与字

UVALive - 3942(trie

Description Neal is very curious about combinatorial problems, and now here comes a problem about words. Knowing that Ray has a photographic memory and this may not trouble him, Neal gives it to Jiejie. Since Jiejie can't remember numbers clearly, he