字典树【训练】

 

字典树(trie):或名前缀树,哈希树的变种,大多题目(非水题)与哈希树套用求解。矮+胖为其显著特征,以空间换时间的典例。

通过利用字符串的公共前缀可实现字符串的快速查询。

板子如下:

#include 
using namespace std;
const int maxn=2e6+5;

int tot=0;
int tree[maxn][30];
int flag[maxn];

void add(char *s)
{
    int len=strlen(s);
    int root=0;
    for(int i=0;i0)
                printf("Yes\n");
            else
                printf("No\n");
        }
    }
    return 0;
}


//前缀出现次数
int trie[400001][26],tot;
int sum[400001];
void add(char *s){
    int root=0;
    int len=strlen(s);
    for(int i=0;i

 

例题:

 

A:

字典树【训练】_第1张图片

字典树【训练】_第2张图片

 

板子题:

#include 
#include 
#include 
#include 
using namespace std;
const int maxn=2e6+5;
int tree[maxn][30],tot=0;//26¸ö×Öĸ
bool flag[maxn];
int sum[100007];
char a[100007];
typedef long long ll;
void add(char *s)
{
    int root=0,id,len=strlen(s);
    for(int i=0;i

 

B:

字典树【训练】_第3张图片

 

思路:有趣题,可通过建双trie储存字符串拼接对比得到结果。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int maxn=2e6+5;
int tree1[maxn][30],tree2[maxn][30];

bool flag1[maxn],flag2[maxn];
int vis[maxn];
int tot1=0,tot2=0;
void add1(char *s){
	int root=0,id,len=strlen(s);
	for(int i=0;i ans; 
int main(){
	int cnt=0;
	while(scanf("%s",a[cnt++])!=EOF){
		add1(a[cnt-1]);
		strrev(a[cnt-1]);
		add2(a[cnt-1]);
		strrev(a[cnt-1]);
	}
	
	for(int i=0;i=2){
				string tp=a[i];
				ans.insert(tp);
				break;
			}
		} 
	}
	for(auto it=ans.begin();it!=ans.end();++it){
		cout<<*it<

 

C:HDU-1251

字典树【训练】_第4张图片

 

 思路:和A类似,板子题

#include 

using namespace std;
const int maxn=2e6+5;
int tree[maxn][30],tot=0;//26¸ö×Öĸ
bool flag[maxn];
int sum[100007];
char a[100007];
typedef long long ll;
void add(char *s)
{
    int root=0,id,len=strlen(s);
    for(int i=0;i

 

 D:Immediate Decodability  HDU-1305

字典树【训练】_第5张图片

字典树【训练】_第6张图片

 

 思路:字典树的第二姿势,即对前缀的查询,稍微改改板子。若有字符串作为其他字符串的前缀,即为可消除的,也就是有一个串上非末尾阶段有flag标记。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int maxn=2e6+5;
int tree[maxn][15],sum[maxn],tot=0;
char a[10005][15];
int T,n;
void add(char *s) {
	int root=0,id,len=strlen(s);
	for(int i=0; i=2)	tp++;
	}
	if(tp==len)	return false;
	else	return true;
}
int main()
{
    int k=1;
    int cnt=0;

    while(scanf("%s",a[cnt])!=EOF){
        if(a[cnt][0]!='9'){
        add(a[cnt]);
        cnt++;
        }
		else{
		    bool pd=0;
            for(int i=0;i

 

 E : What Are You Talking About    HDU - 1075

用map做的,这里就不开了,到时候开map的时候会拿出来写的。

F:Phone List poj-3630

在poj上6w多KB过的,学长搬过来卡内存,就不会了。

也就gg了17发而已。

G: Shortest Prefixes    POJ - 2001

字典树【训练】_第7张图片

字典树【训练】_第8张图片

 

思路:每个每个去找最大的没有flag的地方。

#include 
#include 
#include 
#include 
using namespace std;
const int maxn=2e6+5;
int tree[maxn][30],tot=0;//26¸ö×Öĸ
bool flag[maxn];
int sum[100007];
typedef long long ll;
void add(char *s)
{
    int root=0,id,len=strlen(s);
    for(int i=0; i

 

 

H - 全文检索   HDU - 1277

瞎搞过的,极其难看,这里就不提了。

 

还有几个快乐的题比如说poj的1816,很有意思。

#include 
#include 
#include 
#include 

using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int maxn=2e6+5;
int tree[maxn][30],tot=0;
bool flag[maxn],vis[maxn];
int n,m,p[maxn];
int add(char *s) {
	int root=0,id,len=strlen(s);
	for(int i=0; ilen)	return;
	if(pos==len && flag[root]) {
		vis[root]=1;
	}
	if(tree[root][26]) { //*
		for(int j=pos; j<=len; ++j) {
			fid(s,tree[root][26],j);
		}
	}
	if(tree[root][27]) { //£¿
		fid(s,tree[root][27],pos+1);
	}
	id=s[pos]-'a';
	if(s[pos]>='a'&&s[pos]<='z'&&tree[root][id]) {
		fid(s,tree[root][id],pos+1);
	}
}
char tp[100];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=0;i

 

搞懂哈希之后会继续补的。

转载于:https://www.cnblogs.com/orangeko/p/11219467.html

你可能感兴趣的:(字典树【训练】)