• 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
  • 相关阅读:
    [js]vue-router的使用
    [js]递归实现 数组转树形
    [js]vue组件核心
    [js]了解chart绘图
    [js]vue权限控制
    [js]vue显示一个外部链接的组件
    [js]axios使用
    [js]vue中 给router-view 组件的 绑定 key 的原因
    [java]BeanPostProcessor使用及源码
    [java]权限管理
  • 原文地址:https://www.cnblogs.com/OvOq/p/15029108.html
Copyright © 2020-2023  润新知