acwing第二章学习笔记

文章介绍了单调栈在寻找数组中每个元素右侧最近的较大元素中的应用,以及Trie树(字典树)的基本操作如插入和查找,并展示了如何使用Trie树统计字符串前缀。同时,文章提到了哈希表在解决冲突问题上的两种方法:拉链法和开放地址法。
摘要由CSDN通过智能技术生成

一:单调栈

利用其单调性及先进后出的特点应用:求从右开始离自己最近比自己大的数的脚标.

所有脚标从一开始,若无目标数即输出0。

例:       5

            1 4 2 3 5

输出     2 5 4 5 0

#include<iostream>
#include<stack>
using namespace std;
const int N=1e7;
int a[N],b[N];
int main() {
	int n;
	stack<int> stk;//stk储存的是脚标 
	cin>>n;
	for(int i=1; i<=n; i++)
		scanf("%d",&a[i]);
	for(int i=n; i>=1; i--) 
	{
		while(!stk.empty()&&a[i]>=a[stk.top()])
		stk.pop();
		b[i]=stk.empty()?0:stk.top();
		stk.push(i);
	}
	for(int i=1;i<=n;i++)
	printf("%d ",b[i]);
	return 0;
}

三:trie字典树

例题模板:P8306 【模板】字典树

 

#include<iostream>
#include<string.h>
using namespace std;
const int N=3*1e6+100;
int tot,cnt[N];
int trie[N][65];
char s1[N];
int cast(char x)
{
	if(x>='0'&&x<='9')
	return x-'0';//从第零个开始 
	if(x>='A'&&x<='Z')
	return x-'A'+10;//从第十一个数开始 
	if(x>='a'&&x<='z')
	return x-'a'+36;//从第36个开始 
}
void insert(char s[])
{
	int root=0,len=strlen(s);
	for(int i=0;i<len;i++)
	{
		int step=cast(s[i]);
		if(!trie[root][step])//若此处字符已有记录,则只在cnt中记录+1若无记录则开辟新路,tot++ 
		trie[root][step]=++tot;
		root=trie[root][step];//使root等于下个字符的索引值以方便遍历下一个字符 
		cnt[root]++;//不管是否此处字符有记录都+1. 
	}
}
int find(char s[])
{
	int root=0,len=strlen(s);
	for(int i=0;i<len;i++)
	{
		int step=cast(s[i]);
		if(!trie[root][step])
		return 0;//若此处字符trie树中无记录则说明此字符串不存在于trie中,直接返回0 
		root=trie[root][step];
	}
	return cnt[root];//若上述循环正常结束则说明trie中有记录串s,返回其串结尾字符的出现次数 
}
int main()
{
	int n;
	scanf("%d",&n);
	while(n--)
	{
		for(int i=0;i<=tot;i++)
		for(int j=0;j<65;j++)
		trie[i][j]=0;
		for(int i=0;i<=tot;i++)
		cnt[i]=0;
		tot=0;//注意一定要先初始化数组再初始tot 
		
		int m,q;
		scanf("%d%d",&m,&q);
		while(m--)
		{
			scanf("%s",s1);
			insert(s1);
		}
		while(q--)
		{
			scanf("%s",s1);
			int res=find(s1);
			printf("%d\n",res);
		}
	}
	return 0;
}

注意cnt数组并非存储的是某个字符出现的次数,而是由于此处:if(!trie[root][step]);trie[root][step]=++tot;因此cnt记录的是含有前缀信息的此处字符出现次数。例如字符a:abcd b:fghd。当插入这两个串并且都遍历到结尾'd'时,由于其前缀不同,所以其tot值也不同,在cnt中所存储的值可能也会由于其两个串的出现次数不同而不同。

数字,字符串Hash:

数字Hash拉链法解决冲突:

const int N=1e8;
int h[N],e[N],ne[N],idx=0;//h需初始化为-1 
void Insert(int x)
{
	int key=x%99999989;
	e[idx]=x;ne[idx]=h[key];h[key]=idx++;
}
bool Find(int x)
{
	int key=x%99999989;//取小于hash空间的最大素数 
	for(int i=h[key];i!=-1;i=ne[i])
	{
		if(e[i]==x)
		return true;
	}
	return false;
}

字符串Hash开放地址法解决冲突:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值