zoukankan      html  css  js  c++  java
  • 【bzoj4212】神牛的养成计划

    Portal --> bzoj4212

    Description

    ​  给你(n)个字符串,接下来有(m)个询问,每个询问由两个给定的字符串(s_1)(s_2)组成,对于每个询问输出(n)个字符串中有多少个同时满足(s_1)是其前缀且(s_2)是其后缀,强制在线

    ​​  数据范围:(n<=2000,m<=100000)(n)个字符串总长度以及询问字符串总长度均(<=2000000)

    ​  

    Solution

    ​​  (怎么感觉自己好像没有学过trie一样是因为太久没有写所以根本没有往那个方向想吗==)

    ​  最暴力的做法的话。。想法很简单:先确定哪些字符串满足(s_1)是前缀,再看其中满足(s_2)是后缀的数量

    ​  前缀这种东西的话,如果说我们将(n)个字符串丢到trie里面,将dfs一遍之后各个字符串结尾对应节点的访问顺序存在一个数组里面,那么对于一个询问((s_1,s_2)),满足(s_1)是前缀的字符串的结尾对应节点必定在一个子树当中,反应到数组里面的话就是一个区间

    ​​  那所以接下来我们要做的就是查这个区间内的字符串有多少个满足(s_2)是后缀,只要将所有的串反转然后丢到trie里面,就又转成查前缀的问题了,解决方式和上面一样

    ​​  至于区间这个问题,直接可持久化一下就好了

    ​  

    ​  mark:**没事还是不要随便用getline好了==评测的时候超级容易翻车 **

    ​​  mark:前缀什么的也是应该考虑一下trie啊qwq不要看到字符串什么的就满脑子sa、sam之类的

    ​  

    ​  代码大概长这个样子

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #define mp make_pair
    #define Pr pair<int,int>
    using namespace std;
    const int N=2010,L=2000010,C=26;
    string s[N],s1,s2;
    char tmps[L];
    int st[N],lis[N];
    int n,tot,lastans,m;
    namespace T1{/*{{{*/
    	const int N=::L;
    	int ch[N][C],st[N],ed[N];
    	vector<int> mark[N];
    	int tot,rt;
    	void init(){rt=1;tot=1;}
    	void insert(string s,int id){
    		int len=s.length(),now=rt,c;
    		for (int i=0;i<len;++i){
    			c=s[i]-'a';
    			if (!ch[now][c]) ch[now][c]=++tot;
    			now=ch[now][c];
    		}
    		mark[now].push_back(id);
    	}
    	void dfs(int x){
    		bool have=mark[x].size();
    		if (mark[x].size()){
    			st[x]=lis[0]+1;	
    			for (int i=0;i<mark[x].size();++i)
    				lis[++lis[0]]=mark[x][i];
    		}
    		bool flag=false;
    		for (int i=0;i<C;++i){
    			if (!ch[x][i]) continue;
    			dfs(ch[x][i]);
    			if (!flag&&!have)
    				st[x]=st[ch[x][i]];
    			flag=true;
    		}
    		ed[x]=lis[0];
    	}
    	void get_order(){lis[0]=0; dfs(rt);}
    	Pr query(string s){
    		int now=rt,len=s.length(),c;
    		for (int i=0;i<len;++i){
    			//printf("%c
    ",s[i]);
    			c=(s[i]-'a'+lastans)%C;
    			now=ch[now][c];
    		}
    		if (!now) return mp(-1,-1);
    		return mp(st[now],ed[now]);
    	}
    }/*}}}*/
    namespace T2{/*{{{*/
    	const int N=::L;
    	int ch[N][C],rt[::N],cnt[N];
    	int tot;
    	void init(){tot=0;rt[0]=0;}
    	int newnode(int pre){
    		cnt[++tot]=cnt[pre];
    		for (int i=0;i<C;++i) ch[tot][i]=ch[pre][i];
    		return tot;
    	}
    	void _insert(int pre,int &x,string &s,int loc){
    		x=newnode(pre);
    		++cnt[x];
    		if (loc<0) return;
    		int c=(s[loc]-'a'+lastans)%C;
    		_insert(ch[pre][c],ch[x][c],s,loc-1);
    	}
    	void insert(int pre,int x,string &s){_insert(rt[pre],rt[x],s,s.length()-1);}
    	int query(int l,int r,string s){
    		int nowl=rt[l],nowr=rt[r],c,len=s.length();
    		int ret=0;
    		for (int i=len-1;i>=0&&(nowl||nowr);--i){
    			c=(s[i]-'a'+lastans)%C;
    			nowl=ch[nowl][c];
    			nowr=ch[nowr][c];
    		}
    		return cnt[nowr]-cnt[nowl];
    	}
    }/*}}}*/
    void print(string s){
    	int len=s.length();
    	for (int i=0;i<len;++i) printf("%c",s[i]);
    	printf("
    ");
    }
    void get_s(string &s){
    	scanf("%s",tmps);
    	int len=strlen(tmps);
    	s.resize(0);
    	for (int i=0;i<len;++i)
    		s.push_back(tmps[i]);
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    #endif
    	char ch;
    	Pr rec;
    	scanf("%d
    ",&n);
    	T1::init(); T2::init();
    	lastans=0;
    	for (int i=1;i<=n;++i){
    		get_s(s[i]);
    		//print(s[i]);
    		T1::insert(s[i],i);
    	}
    	T1::get_order();
    	for (int i=1;i<=lis[0];++i){
    		T2::insert(i-1,i,s[lis[i]]);
    	}
    	scanf("%d
    ",&m);
    	for (int i=1;i<=m;++i){
    		get_s(s1);
    		get_s(s2);
    		//print(s1);print(s2);
    		rec=T1::query(s1);
    		if (rec.first!=-1) 
    			lastans=T2::query(rec.first-1,rec.second,s2);
    		else lastans=0;
    		printf("%d
    ",lastans);
    	}
    }
    
  • 相关阅读:
    postfix发信提示 Error: too many connectino from
    postfix 设置邮件头翻译,本域邮件不进行邮件头翻译,仅发送至外网的进行邮件头翻译?
    postfix 如何设置邮件头翻译的功能
    postfix 如何设置邮件头翻译的功能
    Oracle VM VirtualBox如何设置网络地址转换NAT
    python提取百度经验<标题,发布时间,平均流量,总流量,具体的链接>
    css 需要阴影的效果
    django POST表单的使用
    Vim中如何使用正则进行搜索
    Nginx 如何设置反向代理
  • 原文地址:https://www.cnblogs.com/yoyoball/p/9817285.html
Copyright © 2011-2022 走看看