UVALive 3942(使用数据结构trie树加速dp)

《UVALive 3942(使用数据结构trie树加速dp)》

题意:给定一个长度不超过30000的字符串str,然后给定n(n<=4000)个长度不超过100的字符串ai,问用ai组合成str有多少种方案数,最终结果mod20071027。

题解:这里dp[i]表示从len到字符串i有dp[i]种方案,那么前一种的转态dp[i+1]的组合数是由(dp[i+1],i)这一段组成的,我们如何枚举i这一段,如果直接暴力枚举的复杂度将所有子串枚举一遍,O(1e5),然而这只是一次的枚举量,考虑使用tire树,因为子串的长度不会超过100,那么4000个子串我只要在trie树里最多只要查找100个节点就可以了,达到了加速的目的.

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxnode int(4e5+10)
#define sigma_size int(26)
#define mod int(20071027)
using namespace std;
char tmp[200];
char st[maxnode];
int dp[maxnode];
int ch[maxnode][sigma_size];
int val[maxnode];
struct trie
{
	int sz;
	trie() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); }
	int idx(char c) { return c - 'a'; }
	void insert(char *s, int v)
	{
		int u = 0, n = strlen(s);
		for (int i = 0; s[i]; i++)
		{
			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;
	}
	int find(char *s, int pos)
	{
		int ans = 0;
		int u = 0, n = strlen(s);
		for (int i = pos; i < n&&i<=pos+100; i++)
		{
			int c = idx(s[i]);
			if (!ch[u][c]) return ans;
			u = ch[u][c];
			if (val[u])
				ans= (dp[i+1] + ans) % mod;
		}
		return ans;
	}
}tree;
int main()
{
#ifdef CDZSC
	freopen("i.txt", "r", stdin);
#endif
	int n,cas=0;
	while (~scanf("%s", st))
	{
		tree = trie();
		scanf("%d", &n);
		for (int i = 0; i < n; i++)
		{
			scanf("%s", tmp);
			tree.insert(tmp, 1);
		}
		int len = strlen(st);
		dp[len] = 1;
		for (int i = len - 1; i >= 0; i--)
		{
			dp[i] = tree.find(st, i);
		}
		printf("Case %d: %d\n",++cas, dp[0]);
	}
	return 0;
}

    原文作者:Trie树
    原文地址: https://blog.csdn.net/qq_24489717/article/details/50832001
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞