zoukankan      html  css  js  c++  java
  • Trie(2)洛谷题目

    题单: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;
    }
    View Code

    用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;
    }
    View Code

    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;
    }
    View Code

    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;
    }
    View Code
  • 相关阅读:
    docker镜像构建之docker commit(七)
    docker常用容器命令(五)
    docker常用镜像命令(四)
    如何查看systemctl启动服务的日志
    window server 2012 无法安装.NET framework 3.5 service pack 1
    SpringBoot第六篇-SpringBoot+Mybatis+SpringSecurity+JWT整合,开发工具IDea
    SpringBoot第五篇SpringSecurity 认证机制
    SpringBoot第四篇常见问题
    SpringBoot第三篇SpringBoo和Mybatis整合
    SpringBoot第二章拦截器
  • 原文地址:https://www.cnblogs.com/OvOq/p/15029108.html
Copyright © 2011-2022 走看看