Trie专题练习记录 2

HDU 2072 单词数

Solution:

\(Trie\)。解题方法不唯一,此处方法如下。

每一次插入前,判断该字符串是否出现在\(Trie\)中,若出现则满足查询时结尾存在\(endpos[pos]!=0\),跳过。

若没出现过,则\(ans\)加一,将该字符串插入\(Trie\)中,结尾处打上标记\(endpos[pos]=1\)。最后输出\(ans\)即可,注意输入格式和多样例清空。

Code:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<map>
#include<unordered_map>
using namespace std;
const int N=5e5+10;
int tr[N][26];
bool endpos[N];
struct trie{
	int tot;
	int rt;
	void insert(char s[],int lens){
		int pos=rt;
		for(int i=0;i<lens;++i){
			int v = s[i] - 'a';
			if(!tr[pos][v])tr[pos][v]=++tot;
			pos = tr[pos][v];
		}
		endpos[pos] = 1;
	}
	bool query(char s[],int lens){
		int pos=rt;
		for(int i=0;i<lens;++i){
			int v = s[i] - 'a';
			if(!tr[pos][v])return false;
			pos=tr[pos][v];
		}
		return (endpos[pos]!=0);
	}
	void init(){
		tot=rt=0;
	}
};
char s[N];
char newc[N];
int nlen;
int main(){
	trie T;
	T.init();
	int ans=0;
        int c=0;
	while(cin.getline(s,N-1)){
		nlen=0;
		ans=0;
		for(int i=0;i<=T.tot;++i){
			for(int j=0;j<=25;++j)
				tr[i][j]=0;
			endpos[i]=0;
		}
		T.init();
		int lens=strlen(s);
		if(s[0]=='#')break;
		for(int i=0;i<lens;++i){
			if(s[i]==' ')continue;
			int pos=i;
			nlen=0;
			while(s[pos]>='a'&&s[pos]<='z'){
				newc[nlen++]=s[pos];
				pos++;
			}
			i=pos;
			if(T.query(newc,nlen)){
				continue;
			}
			else {
				ans++;
				T.insert(newc,nlen);
			}
		}
		printf("%d\n",ans);
	}
}

HDU 1305 Immediate Decodability

Solution:

\(Trie\)。判断是否有一个串是其他串的前缀。统计所有前缀出现次数,记录下每个串的\(endpos\)位置,如果这些位置存在出现次数大于一,则存在一个串是另一个串的前缀。

Code:

#include<bits/stdc++.h>
using namespace std;
const int N=100005;
const int M=2e5+10;
int tr[M][10];
int endpos[M];
int cnt[M];
int q[M];
struct trie
{
	int tot;//点数
	int rt;//根
	void init(){
		tot=0;
		rt=0;
	}
	void insert(char s[],int lens,int id){
		int pos=rt;
		for(int i=0;i<lens;++i){
			int v=s[i]-'0';
			if(!tr[pos][v])tr[pos][v]=++tot;
			pos=tr[pos][v];
			cnt[pos]++;
		}
		q[id] = pos;
	}
};
char s[N];
int main(){
	trie T;
	T.init();
	int con=0;
	int ca=0;
	while(scanf("%s",s)!=EOF){
		if(s[0]=='9'){
			int flag=1;
			for(int i=1;i<=con;++i){
				if(cnt[q[i]]>1){
					flag=0;
					break;
				}
			}
			if(flag)printf("Set %d is immediately decodable\n",++ca);
			else printf("Set %d is not immediately decodable\n",++ca);
			con=0;
			for(int i=0;i<=T.tot;++i){
				for(int j=0;j<=9;++j){
					tr[i][j]=0;
				}
				cnt[i]=0;
			}
			continue;
		}
		T.insert(s,strlen(s),++con);
	}
	return 0;
}

POJ 3764 The xor-longest Path

Solution:

\(Trie\),树上异或最大值经典题。记录根节点到节点\(i\)的异或和\(q[i]\),那么\(x\)\(y\)两点路径的异或和为\((q[x])xor(q[y])\)
问题转换成给定若干权值,选两个使异或和最大。
考虑依次往\(Trie\)中插入\(q[i]\),每次在插入前查询字典树中与\(q[i]\)的异或最大值为\(val_i\),最后答案显然为\(max(val_i)\)
如何求\(val_i\),异或最大值经典题中有讲解到。

Code:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<map>
using namespace std;
const int N=1e5+10;
int tr[N*10][2];
typedef long long ll;
struct trie{
	int tot;
	int rt;
	void insert(ll val){
		int pos=rt;
		for(ll i=32;i>=0;--i){
			int v = (1&(val>>(i*1ll)));
			if(!tr[pos][v])tr[pos][v]=++tot;
			pos = tr[pos][v];
		}
	}
	ll query(ll val){
		int pos=rt;
		ll ans=0;
		for(ll i=32;i>=0;--i){
			int v = (1&(val>>(i*1ll)));
			if(!tr[pos][v^1]){
				pos=tr[pos][v];
				ans=ans+(1ll*(1<<i))*(v);
			}
			else if(tr[pos][v^1]){
				pos=tr[pos][v^1];
				ans=ans+(1ll*(1<<i))*(v^1);
			}
		}
		return ans;
	}
	void init(){
		tot=rt=0;
	}
};
const int M=N*2;
int ne[M],e[M];
int w[M];
int head[N];
int idx=0;
int n;
void add(int u,int v,int z){
	ne[++idx]=head[u],e[idx]=v,w[idx]=z,head[u]=idx;
}
ll q[N];
void dfs(int u,int fa,ll xsum){
	q[u] = xsum;
	for(int i=head[u];i;i=ne[i]){
		int to = e[i];
		ll z = w[i];
		if(to == fa)continue;
		dfs(to,u,xsum^z);
	}
}
int main(){
	
	trie T;
	while(scanf("%d",&n)!=EOF){
		for(int i=0;i<=T.tot;++i){
			for(int j=0;j<=1;++j){
				tr[i][j]=0;
			}
		}
		for(int i=0;i<n;++i)head[i]=0;
		idx=0;
		T.init();
		for(int i=1;i<=n-1;++i){
			int u,v,z;
			scanf("%d %d %d",&u,&v,&z);
			add(u,v,z);
			add(v,u,z);
		}
		dfs(0,-1,0);
		ll mx=0;

		for(int i=0;i<n;++i){
			mx=max(mx,T.query(q[i])^q[i]);
			T.insert(q[i]);
		}
		printf("%lld\n",mx);
	}
	return 0;
}

POJ 2503 Babelfish

Solution:

\(Trie\)。根据题意模拟即可,方法不唯一。

Code:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<map>
using namespace std;
const int N=5e5+10;
int tr[N][26];
bool endpos[N];
int idpos[N];
int cnt[N];
struct trie{
	int tot;
	int rt;
	void insert(char s[],int lens,int id){
		int pos=rt;
		for(int i=0;i<lens;++i){
			int v = s[i] - 'a';
			if(!tr[pos][v])tr[pos][v]=++tot;
			pos = tr[pos][v];
			idpos[pos]=id;
		}
	}
	int query(char s[],int lens){
		int pos=rt;
		int ans=0;
		for(int i=0;i<lens;++i){
			int v = s[i] - 'a';
			if(!tr[pos][v])return false;
			pos=tr[pos][v];
		}
		return idpos[pos];
	}
	void init(){
		tot=rt=0;
	}
};
char s1[100001][11];
char s2[100001][11];
char s[23];
int main(){
	trie T;
	T.init();
	int con=0;
	while(cin.getline(s,22)){
		int len=strlen(s);
		if(len==0)break;
		int pos=0;
		++con;
		for(int i=0;i<len;++i){
			if(s[i]==' '){
				pos=i;break;
			}
			s1[con][i]=s[i];
		}
		int cc=0;
		for(int i=pos+1;i<len;++i){
			s2[con][cc++]=s[i];
		}
		T.insert(s2[con],cc,con);
	}

	while(scanf("%s",s)!=EOF){
		int len=strlen(s);
		int va=T.query(s,len);
		if(va==0)puts("eh");
		else printf("%s\n",s1[va]);
	}
}

HDU 1247 Hat’s Words

Solution:

\(Trie\)。每个单词的最大长度不超过\(50\)
先将所有字符串长度从小到大排序,保证字符串\(i\)的可能前缀在\([1,i-1]\)中已经插入。
查询时枚举前缀,遇到\(endpos=1\)的位置时,截取字符串,返回根节点重新查询剩余部分,若最后剩余部分结尾存在\(endpos=1\),则该字符串符合答案要求。
将所有答案按字典序排序,注意输出即可。

Code:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<map>
#include<unordered_map>
using namespace std;
const int N=2e5+10;
int tr[N][26];
bool endpos[N];
struct trie{
	int tot;
	int rt;
	void insert(char s[],int lens,int id){
		int pos=rt;
		for(int i=0;i<lens;++i){
			int v = s[i] - 'a';
			if(!tr[pos][v])tr[pos][v]=++tot;
			pos = tr[pos][v];
		}
		endpos[pos] = 1;
	}
	bool query(char s[],int lens){
		int pos=rt;
		for(int i=0;i<lens;++i){
			int v = s[i] - 'a';
			if(!tr[pos][v])return false;
			pos=tr[pos][v];
			if(endpos[pos]){
				if(query1(s,i+1,lens))return true;	
			}
		}
		return false;
	}
	bool query1(char s[],int st,int lens){
		int pos=rt;
		for(int i=st;i<lens;++i){
			int v=s[i] - 'a';
			if(!tr[pos][v])return false;
			pos=tr[pos][v];
		}
		if(endpos[pos]){
			return true;
		}
		else return false;
	}
	void init(){
		tot=rt=0;
	}
};
bool cmp(string a,string b){
	return (int)a.length()<(int)b.length();
}
bool cmp1(string a,string b){
	return a<b;
}
string ans[N];
char newc[N];
int ansid[N];
string s[N];
int main(){
	trie T;
	T.init();
	string ss;
	int con=0;
	while(cin>>ss){
		s[++con]=ss;
	}
	sort(s+1,s+1+con,cmp);
	int cans=0;
	for(int i=1;i<=con;++i){
		int cnt=0;
		int len=s[i].size();
		for(int j=0;j<len;++j){
			newc[cnt++]=s[i][j];
		}
		if(T.query(newc,len)){
			ans[++cans]=s[i];
		}
		T.insert(newc,cnt,i);
	}
	
	sort(ans+1,ans+1+cans,cmp1);
	for(int i=1;i<=cans;++i){
		cout<<ans[i]<<"\n";
	}
	return 0;
}

posted @ 2021-07-13 14:28  Qquun  阅读(34)  评论(0)    收藏  举报