Uva1401

初步的转移想法是一种 n2

就是 O(n) 枚举位置再 O(n) 枚举断点转移的那种

发现单词的长度不超过 100,就可以暴力了

每个位置匹配一下就可以了

由于不会有重复单词,用 Trie 树来‘加速’匹配


 代码:

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

const int MAXL = 300005, MAXS = 4005, mod = 20071027;

struct Node {
	int nxt[26];
	bool isend;
}t[MAXS * 105];
char txt[MAXL], wrd[105];
int s, ptr, len, tot;
int f[MAXL];

inline int newnode() {
	++ptr;
	memset(t + ptr, 0, sizeof(Node));
	return ptr;
}
inline void Insert(char *s) {
	register int LEN = strlen(s), cur = 0;
	for (int i = 0; i < LEN; ++i) {
		register int x = s[i] - 'a';
		if (!t[cur].nxt[x]) t[cur].nxt[x] = newnode();
		cur = t[cur].nxt[x];
	}
	t[cur].isend = true;
}
inline void work(int pos) {
	register int cur = 0;
	for (int i = pos; i < len; ++i) {
		register int x = txt[i] - 'a';
		if (!t[cur].nxt[x]) return;
		cur = t[cur].nxt[x];
		if (t[cur].isend) f[pos] = (f[pos] + f[i + 1]) % mod;
	}
}
inline void clearall() {
	memset(f, 0, sizeof(f));
	memset(t + 0, 0, sizeof(Node));
	ptr = 0;
	return;
}

int main() {
	while (~scanf("%s", txt)) {
		clearall();
		scanf("%d", &s);
		for (int i = 1; i <= s; ++i) {
			scanf("%s", wrd);
			Insert(wrd);
		}
		len = strlen(txt);
		f[len] = 1;
		for (int i = len - 1; i >= 0; --i)
			work(i);
		printf("Case %d: %d\n", ++tot, f[0]);
	}
	return 0;
}
posted @ 2018-10-27 19:21  EvalonXing  阅读(140)  评论(0编辑  收藏  举报