『一本通』Trie字典树
Phone List
#include<bits/stdc++.h> using namespace std; const int N=1e5+5; int T,n,tot,c[N][10]; char s[10]; bool ans,bo[N]; void clear() { tot=0,ans=0; memset(c,0,sizeof(c)); memset(bo,false,sizeof(bo)); } bool insert() { int len=strlen(s+1),u=0; bool flag=0; for(int i=1;i<=len;i++) { int v=s[i]-'0'; if(!c[u][v]) c[u][v]=++tot; else if(i==len) flag=1; //没有插入任何新节点 u=c[u][v]; if(bo[u]) flag=1; } bo[u]=1; return flag; } int main() { scanf("%d",&T); while(T--) { clear(); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%s",s+1); if(insert()) ans=1; } printf("%s\n",ans?"NO":"YES"); } }
The XOR Largest Pair
将$A[i]$看作长度为$32$的二进制$01$串,插入$Trie$字典树。
对于$A[i]$对应的$32$位二进制串,我们从高位到低位,尽量沿着“与$A[i]$当前位相反的字符指针”向下访问。
根据$xor$运算“相同得0,不同得1”的性质,即可找出与$A[i]$做$xor$运算结果最大的$A[j]$。
#include<bits/stdc++.h> using namespace std; const int O=1e5*30; int n,x,tot,ans,c[O][2]; void insert(int x) { int u=0; for(int i=30;i>=0;i--) { int v=(x>>i)&1; if(!c[u][v]) c[u][v]=++tot; u=c[u][v]; } } int cal(int x) { int u=0,res=0; for(int i=30;i>=0;i--) { int v=(x>>i)&1; if(c[u][v^1]) res+=1<<i,u=c[u][v^1]; else u=c[u][v]; } return res; } int main() { scanf("%d",&n); while(n--) { scanf("%d",&x); ans=max(ans,cal(x)); insert(x); } printf("%d",ans); }
背单词
将所有字符串倒着插入字典树,使后缀变为前缀。
贪心:不能出现情况1。如果$s1$为$s$的后缀,那么$s1$的序号必须小于$s$的序号。
要使结点的序号减去其儿子的序号最小,我们从小到大遍历每个结点的子树即可。
#include<bits/stdc++.h> using namespace std; const int N=510000+5; int n,tot,cnt,w[N],fro[N],siz[N],fa[N],c[N][26]; long long ans; bool bo[N]; char s[N]; struct edge{int to,nxt;}a[N]; vector<int>vi[N]; void add(int x,int y) { a[++cnt].to=y,a[cnt].nxt=fro[x]; fro[x]=cnt; } void insert(int x) { int len=strlen(s+1),u=0; for(int i=len;i>0;i--) { int v=s[i]-'a'; if(!c[u][v]) c[u][v]=++tot,fa[tot]=u; u=c[u][v]; } bo[u]=1,w[x]=u; } void dfs(int u) { siz[u]=1; for(int i=fro[u];i;i=a[i].nxt) { int v=a[i].to; dfs(v); siz[u]+=siz[v]; vi[u].push_back(siz[v]); } sort(vi[u].begin(),vi[u].end()); int num=0; for(int i=0;i<vi[u].size();i++) ans+=num+1,num+=vi[u][i]; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%s",s+1); insert(i); } for(int i=1;i<=n;i++) { int k=fa[w[i]]; while(k&&!bo[k]) k=fa[k]; add(k,w[i]); } dfs(0); printf("%lld",ans); }
如有错误请指正。