字典树(trie)模板

喵喵的IDE

Time Limit: 20000/10000MS (Java/Others) Memory Limit: 512000/256000KB (Java/Others)
Problem Description

喵喵有一个神奇的IDE,这个IDE自带一个cache,还有一个当前编辑区editarea,初始的时候这个 cache 中有一个字符串 cachebegin

喵喵想打按照顺序打N个字符串 x,她可以进行三种操作。

打之前 editarea 为空
1、从cache中拿出一个字符串 B直接赋值给editarea , editarea = B.(如果不拿那么不计入操作数)
2、如果editarea里面有字符,那wuyiqi可以删除掉editarea中最后一个字符。(删光了之后就不能删除啦!)
3、喵喵可以在editarea末尾插入一个任意字符。
如果editarea的字符串恰好与她要打的第i个字符串相同,那么她就完成了这次打印,并且这个字符串自动加入cache(cache中可能出现重复字符串),然后editarea自动清空。那么喵喵就会自动进入下一个字符串的打印阶段。
她想问,对于每次字符串输出,最少需要多少次操作。
1 ≤ N ≤ 105 , 字符串长度总和 ∑(Ai) <106 , cache_begin 长度< 100

Input

第一行一个整数T,代表数据组数。

对于每组数据第一行一个整数 N 代表要打印的字符串个数,还有一个字符串cachebegin

以下N 行每行一个字符串 Ai

A和 cachebegin 都只包含小写字母

Output
对于每组测试数据输出N个数。
Sample Input
1
3 a
a
ab
abc
Sample Output
1
2
2
Hint

一开始cache中为{"a"}
第一次操作直接拿出来{"a"}就好了

现在cache为{"a","a"}
拿出来"a",加入b,两次操作。

现在cache为{"a" , "a" , "ab"}
拿出来"ab",加入c。两次操作


第一次可以从缓存中拿出字符串进行操作,删除末尾字符或者在末尾加入任意字符,使得最小步数获得新的字符串并加入缓存中。用字典树(trie)来存储字符串并进行查找,注意,字典树构建内存分配必须是连续的还是怎样。trie.v表示从当前位置到末尾还有多少个字符。


#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
struct trie
{
	trie * son[26];
	int v;
	trie()
	{
		for (int i=0;i<26;i++)
			son[i]=NULL;v=0;	
	}
}*root,k[1000010];
int t=0;
char a[1000010];
void insert(trie *rt,int l)
{
	for (int i=0;i<l;i++)
	{
		int c=a[i]-'a';
		if (rt->son[c]==NULL)
		{
			k[++t]=trie();
			rt->son[c]=&k[t];
			rt->son[c]->v=l-1-i;
		}
		else
		if (rt->son[c]->v>l-1-i)
			rt->son[c]->v=l-1-i;
		rt=rt->son[c];
	}
}
int getanswer(trie * rt,int l)
{
	int ans=l;
	for (int i=0;i<l;i++)
	{
		int c=a[i]-'a';
		if (rt->son[c]==NULL) break;
		else
		{
			if (ans>rt->son[c]->v+l-i)
				ans=rt->son[c]->v+l-i;
		}
		rt=rt->son[c];
	}
	return ans;
}
int main()
{
	int T,n;
	scanf("%d",&T);
	while (T--)
	{
		t=-1;
		scanf("%d %s",&n,a);
		k[++t]=trie();
		root=&k[t];
		int l=strlen(a);
		insert(root,l);
		while (n--)
		{
			scanf("%s",a);
			l=strlen(a);
			int ans=getanswer(root,l);
			insert(root,l);
			printf("%d\n",ans);
		}
	}
	return 0;
}

上个版本太渣了,内存容易爆栈。来个用new新建内存的方案。顺便把原题附上:http://hihocoder.com/contest/hiho2/rank

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
struct trie
{
	trie * son[30];
	int v[30];
	trie()
	{
		for (int i=0;i<30;i++)
		{	
			son[i]=NULL;
			v[i]=0;
		}
	}
}*root;
int t,n;
char s[30];
void insert(trie * rt,int l)
{
	for (int i=0;i<l;i++)
	{
		int c=s[i]-'a';
		if (rt->son[c]==NULL)
		{
			trie *rit=new trie();
			rt->son[c]=rit;
			rt->son[c]->v[c]=1;
		}
		else rt->son[c]->v[c]++;
		rt=rt->son[c];
	}
}
int getans(trie * rt,int l)
{
	int ans=0;
	for (int i=0;i<l;i++)
	{
		int c=s[i]-'a';
		if (rt->son[c]==NULL) return 0;
		else ans=rt->son[c]->v[c];
		rt=rt->son[c];
	}
	return ans;
}
/*void del(trie * root)
{
	for(int i=0;i<30;i++)
    {
        if(root->son[i]!=NULL)
            del(root->son[i]);
    }
    free(root);
}*/
int main()
{
	scanf("%d",&n);
	t=0;
	root=new trie();
	getchar();
	for (int i=0;i<n;i++)
	{
		scanf("%s",&s);
		int l=strlen(s);
		insert(root,l);
	}
	scanf("%d",&n);
	getchar();
	for (int i=0;i<n;i++)
	{
		scanf("%s",&s);
		int l=strlen(s);
		printf("%d\n",getans(root,l));
	}
	delete root;
   // del(root);
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值