• P2922 [USACO08DEC]Secret Message G


    字典树很好的一道题

    这个题区别于一般的字典树前缀匹配在于

    匹配的字符串可能比字典树上的长 也可能比字典树上的短

    如果只是维护一个节点会被经过多少次肯定是没法解的

    考虑再维护一个endd数组 表示以i节点为结尾的字符串数量

    在查找的时候 比匹配字符串短的节点直接+endd数组即可

    经过节点数sum就不行 因为我们只找匹配字符这一条线上的 但是sum是维护这个节点以下所有的

    比匹配字符长的就可以直接加sum数组就好 这就回到了一般的字典树查找

    但是要注意的是要减去endd{root} 因为这个会被加上两次 sum和endd都包含了

    #include<bits/stdc++.h>
    using namespace std;
    #define lowbit(x) x&(-x)
    #define ll long long
    const int maxn=5e5+5;
    int n,m,cnt;
    int tr[maxn][2],sum[maxn],endd[maxn]; 
    void insert(string x);
    int serach(string x);
    int main(){
    	cin>>m>>n;
    	for(int i=0;i<maxn;i++)
    	for(int j=0;j<2;j++)
    	tr[i][j]=-1;
    	for(int i=1;i<=m;i++){
    		int bi;cin>>bi;
    		stringstream ss;//黑科技 很好用的
    		for(int j=1;j<=bi;j++){
    			int xi;cin>>xi;
    			ss<<xi;
    		}
    		string s;ss>>s;
    		insert(s);
    	}
    	for(int i=1;i<=n;i++){
    		int bi;cin>>bi;
    		stringstream ss;
    		for(int j=1;j<=bi;j++){
    			int xi;cin>>xi;
    			ss<<xi;
    		}
    		string s;ss>>s;
    		cout<<serach(s)<<endl;
    	}
         return 0;
    }
    void insert(string x){
    	int root=0;
    	for(int i=0;i<x.size();i++){
    		int id=x[i]-'0';
    		if(tr[root][id]==-1)tr[root][id]=++cnt;
    		root=tr[root][id];sum[root]++;
    	}
    	endd[root]++;
    }
    int serach(string x){
    	int root=0,res=0;
    	for(int i=0;i<x.size();i++){
    		int id=x[i]-'0';
    		if(tr[root][id]==-1)return res;
    		root=tr[root][id];
    		res+=endd[root]; 
    	}
    	return res-endd[root]+sum[root];
    }
  • 相关阅读:
    使用keras构建简单的网络分类鸢尾花
    矩阵的秩 rank(A)
    矩阵的迹
    数学符号大全速查表
    迷茫的不是青春,是你们回望青春时失焦的眼神。
    服务器Windows Server 2008 远程控制安全设置技巧
    服务器安全维护配置和优化八大要点
    怎么把html页面中共用的底部代码做成共享模块
    回首2017,展望2018,今后的路我们一起走
    手机端rem如何适配_rem详解及使用方法2
  • 原文地址:https://www.cnblogs.com/wzxbeliever/p/16085724.html
Copyright © 2020-2023  润新知