HDU - 6096

题目链接:HDU - 6096


前后缀分开的,很麻烦,所以想办法拼凑在一起。

对每个字符串例如1234 ,我们构造成 1 4 2 3 3 2 4 1

然后对查询的串一样构造即可,当某个不存在时,用特殊符号代替。

然后防止前后串重叠,所以我们按照长度排序。离线做。如果强制在线的话,就只能换成可持久化Trie了


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e6+10;
int n,q,t[N][26],idx,res[N],sz[N]; string str,s,tmp;
struct node{string s; int sz,f,id;}a[N<<1];
inline void insert(string &str){
	int p=0;
	for(int i=0;i<str.size();i++){
		int k=str[i]-'a';
		if(!t[p][k])	t[p][k]=++idx;
		p=t[p][k];	sz[p]++;
	}
}
int ask(int x,int p,string &str){
	if(x==str.size())	return sz[p];
	int res=0;
	if(str[x]=='*'){
		for(int i=0;i<26;i++)	if(t[p][i])	res+=ask(x+1,t[p][i],str);
	}else	if(t[p][str[x]-'a'])	res+=ask(x+1,t[p][str[x]-'a'],str);
	return res;
}
void solve(){
	cin>>n>>q; memset(t,0,sizeof t); idx=0; memset(sz,0,sizeof sz);
	for(int i=1,l,r,f;i<=n;i++){
		cin>>str; tmp=""; l=0,r=str.size()-1,f=1;
		while(r>=0){
			if(f)	tmp+=str[l++];
			else	tmp+=str[r--];
			f^=1;
		}
		a[i].s=tmp,a[i].sz=str.size(),a[i].f=0;
	}
	for(int i=1,l,r,f;i<=q;i++){
		cin>>str>>s; tmp=""; l=0,r=s.size()-1,f=1;
		while(l<str.size()||r>=0){
			if(f)	tmp+=(l==str.size()?'*':str[l++]);
			else	tmp+=(r>=0?s[r--]:'*');
			f^=1;
		}
		a[i+n].s=tmp,a[i+n].sz=str.size()+s.size(),a[i+n].f=1,a[i+n].id=i;
	}
	sort(a+1,a+1+n+q,[](node a,node b){return a.sz==b.sz?a.f<b.f:a.sz>b.sz;});
	for(int i=1;i<=n+q;i++){
		if(!a[i].f)	insert(a[i].s);
		else	res[a[i].id]=ask(0,0,a[i].s);
	}
	for(int i=1;i<=q;i++)	cout<<res[i]<<'\n';
}
signed main(){
	ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
	int T; cin>>T; while(T--) solve();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/107747866
hdu