电子学会七级-数据结构-字典树

于是他错误的点名开始了
https://www.luogu.com.cn/problem/P2580

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
int son[30][maxn],idx=0;
int cnt[maxn];
map<string,bool> pp;//记录是否有重复询问 

void insert(string s){
	int p=0;//root位置 
	for(int i=0;i<s.size();i++){//字符串每个字符存放对应位置 
		int u=s[i]-'a';//取对应字母的ascii码 
		if(!son[u][p]){//如果孩子节点没出现 u 则u放入到孩子节点 idx+1 
			son[u][p]=++idx;//idx+1 放入u节点 对应idx编号累加 
		}
		p=son[u][p];//更新p的位置 
	}
	cnt[p]=1;//字符结尾 标记为1 
}

string ask(string s){
	int p=0;//从root 为0开始 
	for(int i=0;i<s.size();i++){//从第一个字符逐一查找 
		int u=s[i]-'a';//u为s[i]字符对应ASCIII码 
		if(!son[u][p]){//如果u不存在 则找不到 
			return "WRONG";
		}
		p=son[u][p];//更新根节点编号 
	}
	if(cnt[p])//是结尾 则找到 
		return "OK";
}

int main(){
	int n;//n个同学 
	cin>>n;
	for(int i=1;i<=n;i++){
		string s;
		cin>>s;//输入班上人的名字 
		insert(s);//插入到字典序 
	}
	int m;
	cin>>m;//m次询问 
	for(int i=1;i<=m;i++){
		string s;
		cin>>s;//询问字符串 
		if(!pp[s]){//未询问过 
			cout<<ask(s)<<endl;
		}else{//询问过 
			cout<<"REPEAT"<<endl;
		}
		pp[s]=1;//询问过更新标识 
	}
}

合并序列
https://www.luogu.com.cn/problem/P1628

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
int N,idx,tidx;//N个单词 
int cnt[maxn]; 
int son[30][maxn];//二维数组存储字典树 
string fstr;//查找的字符串 
char ans[110];// dfs查找每个单词字符数组  --不包括前缀 abcd 前缀t为ab 则只存储cd 
void insert(string s){//构建字典树 
	int p=0;
	for(int i=0;i<s.size();i++){//为每个字符构建字典树 
		int u=s[i]-'a';//u为 s[i]相对a的位置 
		if(!son[u][p]){//如果没有这个字符 新增一个 
			son[u][p]=++idx;//这个字符占用这个位置 
		}
		p=son[u][p];//记录对应下标值 
	}
	cnt[p]++;//标记结尾 
}
//从某个位置继续找已查找字符串为前缀的后面字符 
void dfs(int p){
	while(cnt[p]--){//是结尾 输出 退出dfs 
		cout<<fstr;//查找字符前缀 
		for(int i=0;i<tidx;i++){//查找字符后续字符 
			cout<<ans[i];
		}
		cout<<endl;//换行 
	}
	for(int i=0;i<26;i++){//枚举26个字母 下一个编号为p的字符 
		if(son[i][p]){//如果找到 
			int p1=p;//暂存位置 
			p=son[i][p];//下个字符位置 
			ans[tidx++]=i+'a';//记录找到字符 
			dfs(p);//继续往下找 
			p=p1;//恢复p位置 
			tidx--;//恢复记录字符数组下标 
		}
	}
}

int main(){
	cin>>N;
	for(int i=0;i<N;i++){//输入N个词 并构建字典树 
		string s;
		cin>>s;
		insert(s);
	}
	
	cin>>fstr;//输入待匹配的前缀 
	int p=0;//从字典树0位置查找 
	for(int i=0;i<fstr.size();i++){//一定可以查找到 
		int u=fstr[i]-'a';
		p=son[u][p];//记录最后一个位置 
	}
	dfs(p);//从此位置dfs查找对应单词 
	return 0;
}

魔族密码
https://www.luogu.com.cn/problem/P1481

洛谷的文件夹
https://www.luogu.com.cn/problem/P1738

前缀统计
https://www.acwing.com/problem/content/144/
最大异或对
https://www.acwing.com/problem/content/145/
最长异或值路径
https://www.acwing.com/problem/content/146/

posted @ 2022-04-19 16:56  new-code  阅读(20)  评论(0编辑  收藏  举报