oi-wiki

主要用途:

  1. 检索字符串
  2. 求异或类型
    1. 维护异或极值
    2. 维护异或和

模板

struct trie {
  int nex[100000][26], cnt;
  bool exist[100000];  // 该结点结尾的字符串是否存在

  void insert(char *s, int l) {  // 插入字符串
    int p = 0;
    for (int i = 0; i < l; i++) {
      int c = s[i] - 'a';
      if (!nex[p][c]) nex[p][c] = ++cnt;  // 如果没有,就添加结点
      p = nex[p][c];
    }
    exist[p] = 1;
  }
  bool find(char *s, int l) {  // 查找字符串
    int p = 0;
    for (int i = 0; i < l; i++) {
      int c = s[i] - 'a';
      if (!nex[p][c]) return 0;
      p = nex[p][c];
    }
    return exist[p];
  }
};

从oi-wiki 上的模板贺过来的(其实是懒得自己打(逃

例题:于是他错误的点名开始了

只要对于出现的名字建 Trie ,再使用 Trie 查询字符串是否存在即可。

code:

#include<bits/stdc++.h>
using namespace std;

const int N=1e6+10;
struct node{int sn[27],num;}a[N];
int cnt,n,m,res;char ch[55];

void build()//建 Trie
{
	int l=strlen(ch),p=0;
	for(int i=0;i<l;i++)
	{
		if(!a[p].sn[ch[i]-'a']) a[p].sn[ch[i]-'a']=++cnt;
		p=a[p].sn[ch[i]-'a'];
	}
}

int qry()//查找字符串
{
	int l=strlen(ch),p=0;
	for(int i=0;i<l;i++)
	{
		if(!a[p].sn[ch[i]-'a']) return 0;
		p=a[p].sn[ch[i]-'a'];
	}
	return ++a[p].num;
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%s",ch),build();
	scanf("%d",&m);
	while(m--)
	{
		scanf("%s",ch);res=qry();
		if(res==0) puts("WRONG");
		else if(res==1) puts("OK");
		else if(res>=2) puts("REPEAT");
	}
	return 0;
}

两两异或中的最大值

#include<bits/stdc++.h>
using namespace std;

const int N=1e6+10;
int n,T,num,ans,x[N];string tp;
struct node{
	int ch[3],sum;bool fla;
	void clr(){memset(ch,0,sizeof ch);sum=fla=0;}
}t[N<<2];

void inst(string s)
{
	int sz=s.size(),a=0;
	for(int i=0;i<sz;i++)
	{
		int b=s[i]-'0';
		if(!t[a].ch[b]) t[a].ch[b]=++num;
		t[a].sum++,a=t[a].ch[b];
	}
}

int fnd(string s)//查找最大值
//在 Trie 上用贪心的思想尽量往于当前相反的节点跑
//如果没有就只能走原来的数位,根据异或的运算法则,可以得到两个数异或的最大值的
//
{
	int sz=s.size(),a=0,res=0,nu=(INT_MAX)/2+1;
	for(int i=0;i<sz;i++)
	{
		int b=(s[i]-'0')^1;
		if(!t[a].ch[b]) b^=1;else res+=nu;
		a=t[a].ch[b];nu/=2;
	}return res;
}

string inbit(int x)//把每个数转化为二进制存入 Trie 中
//注意转化时倒着存储,方便更新答案
{
	string res="";
	while(x) res+=(x%2)+'0',x>>=1;
	while(res.size()!=31) res+='0';
	reverse(res.begin(),res.end());
	return res;
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) 
		scanf("%d",&x[i]),tp=inbit(x[i]),inst(tp);
	for(int i=1;i<=n;i++) ans=max(ans,fnd(inbit(x[i])));
	printf("%d",ans);
	return 0;
}

两个不相交区间的异或值相加最大值

咕咕咕ing

\(\texttt{End.}\)