题单:https://www.luogu.com.cn/training/9372
P3879 [TJOI2010]阅读理解
题型:字符串检索
空间卡的很紧,普通的trie会MLE
const int maxn=5e5+100; bool st[maxn][1010]; int nex[maxn][26],cnt=0; void insert(string s,int l,int x){ // 插入字符串 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]; } st[p][x]=1; } int find(string 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 p; } int main(){ int n=read; rep(q,1,n){ int k=read; rep(i,1,k){ string s;cin>>s; insert(s,s.size(),q); } } int m=read; while(m--){ string s;cin>>s; if(int t=find(s,s.size())){ rep(i,1,n) if(st[t][i]) cout<<i<<" "; } puts(""); } return 0; }
用bitset优化掉标记数组的空间
const int maxn=5e5+100; bitset<1001> st[500007]; int nex[maxn][26],cnt=0; void insert(string s,int l,int x){ // 插入字符串 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]; } st[p][x]=1; } int find(string 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 p; } int main(){ int n=read; rep(q,1,n){ int k=read; rep(i,1,k){ string s;cin>>s; insert(s,s.size(),q); } } int m=read; while(m--){ string s;cin>>s; if(int t=find(s,s.size())){ rep(i,1,n) if(st[t][i]) cout<<i<<" "; } puts(""); } return 0; }
P2922 [USACO08DEC]Secret Message G
题型:多询问多前缀统计
注意加上前缀相同并且长度比他长的个数,减掉字符串相等的个数,因为重复计算了。
const int maxn=5e5+100; int sum[maxn],now[maxn]; int nex[maxn][26],cnt=0; int s[maxn]; int find(int s[],int x){ int p=0,res=0; rep(i,0,x-1){ int c=s[i]; if(!nex[p][c]) return res; p=nex[p][c]; res+=now[p]; } return res-now[p]+sum[p]; } int main(){ int m=read,n=read; while(m--){ int x=read; int p=0; for(int i=0;i<x;i++){ int c=read; if(!nex[p][c]) nex[p][c]=++cnt;// 如果没有,就添加结点 p=nex[p][c]; sum[p]++; } now[p]++; } while(n--){ int x=read; rep(i,0,x-1) s[i]=read; cout<<find(s,x)<<endl; } return 0; }
P4551 最长异或路径
前置知识 https://www.acwing.com/problem/content/145/
const int maxn=1e6+100; vector<PII>g[maxn]; int dis[maxn]; void dfs(int u,int fa){ for(int i=0;i<g[u].size();i++){ int j=g[u][i].first,w=g[u][i].second; if(j==fa) continue; dis[j]=dis[u]^w; dfs(j,u); } } int nex[maxn][2],idx; void insert(int x){ int p=0; for(int i=31;i>=0;i--){ int &s=nex[p][x>>i&1]; if(!s) s=++idx; p=s; } } int search(int x) { int p = 0, res = 0; for (int i = 31; i >= 0; i -- ) { int s = x >> i & 1; if (nex[p][!s]) { res += 1 << i; p = nex[p][!s]; } else p = nex[p][s]; } return res; } int main(){ int n=read; rep(i,1,n-1){ int u=read,v=read,w=read; g[u].push_back({v,w}); g[v].push_back({u,w}); } dfs(1,-1); for(int i=1;i<=n;i++) insert(dis[i]); int res = 0; for (int i = 1; i <= n; i ++ ) res = max(res, search(dis[i])); cout<<res<<endl; return 0; }