CQOI2014 通配符匹配

发布时间:2024年01月24日

P3167 [CQOI2014] 通配符匹配

题目大意

常见的通配符有以下两种:

  • *:可以匹配 0 0 0个及以上的任意字符
  • ?:可以匹配一个任意字符

给定一个由通配符和小写字母组成的字符串 S S S n n n个由小写字母组成的字符串 T i T_i Ti?,求每个 T i T_i Ti?能否被通配字符串 S S S通配。

1 ≤ n ≤ 100 1\leq n\leq 100 1n100

字符串长度不超过 1 0 5 10^5 105,通配符个数不超过 10 10 10


题解

依题意,通配符个数不超过 10 10 10,那么我们可以以通配符为界限,将通配串分为若干段。

设通配串能分为 m m m段(也就是有 m ? 1 m-1 m?1个通配符), o p i op_i opi?表示第 i i i段之前的通配符( 0 0 0表示没有, 1 1 1表示? 2 2 2表示*), l e n i len_i leni?表示第 i i i段的长度。

对于每个 T k T_k Tk?,我们考虑如何判断其能否被通配字符串通配。设 f i , j f_{i,j} fi,j?表示第 i i i段的结尾能否匹配上 T k T_k Tk?的第 j j j个字符。那么,转移方程为

f i , j = { f i ? 1 , j ? l e n i o p i = 0 f i ? 1 , j ? l e n i ? 1 o p i = 1 ∑ t = 0 j ? l e n i f i ? 1 , k o p i = 2 f_{i,j}= \left\{\begin{matrix} f_{i-1,j-len_i} &op_i=0 \\ f_{i-1,j-len_i-1} &op_i=1 \\ \sum\limits_{t=0}^{j-len_i}f_{i-1,k} &op_i=2 \end{matrix}\right. fi,j?=? ? ??fi?1,j?leni??fi?1,j?leni??1?t=0j?leni??fi?1,k??opi?=0opi?=1opi?=2?

用哈希来判断能否转移即可。

答案为 f m , ∣ T k ∣ f_{m,|T_k|} fm,Tk??

时间复杂度为 O ( ∣ S ∣ + m ∑ ∣ T k ∣ ) O(|S|+m\sum|T_k|) O(S+mTk?)

code

#include<bits/stdc++.h>
using namespace std;
const int N=100000;
const int base=31;
const long long mod=1e9+7;
int T,s1,t1,w1=0,f[15][N+5];
long long bw[N+5],h[N+5],sf[15][N+5];
char s[N+5],t[N+5];
struct node{
	int bg,ed,op;
	long long hsh;
}w[15];
void init(){
	bw[0]=1;
	for(int i=1;i<=N;i++){
		bw[i]=bw[i-1]*base%mod;
	}
}
void solve_s(){
	s1=strlen(s+1);
	w[++w1].bg=1;
	w[w1].op=0;
	for(int i=1;i<=s1;i++){
		if(s[i]=='?'||s[i]=='*'){
			w[w1].ed=i-1;
			w[++w1].bg=i+1;
			if(s[i]=='?') w[w1].op=1;
			else w[w1].op=2;
		}
	}
	w[w1].ed=s1;
	for(int i=1;i<=w1;i++){
		w[i].hsh=0;
		for(int j=w[i].bg;j<=w[i].ed;j++){
			w[i].hsh=(w[i].hsh*base+s[j]-'a'+1)%mod;
		}
	}
}
void solve_t(){
	t1=strlen(t+1);
	for(int i=1;i<=t1;i++){
		h[i]=(h[i-1]*base+t[i]-'a'+1)%mod;
	}
}
long long gthsh(int l,int r){
	return (h[r]-h[l-1]*bw[r-l+1]%mod+mod)%mod;
}
void solve_dp(){
	for(int i=0;i<=w1;i++){
		for(int j=0;j<=t1;j++) sf[i][j]=f[i][j]=0;
	}
	if(gthsh(1,w[1].ed-w[1].bg+1)!=w[1].hsh) return;
	f[1][w[1].ed-w[1].bg+1]=1;
	for(int i=2;i<=w1;i++){
		sf[i-1][0]=f[i-1][0];
		for(int j=1;j<=t1;j++){
			sf[i-1][j]=sf[i-1][j-1]|f[i-1][j];
		}
		int len=w[i].ed-w[i].bg+1;
		for(int j=1;j<=t1;j++){
			if(w[i].op==1){
				if(j-len-1>=0&&gthsh(j-len+1,j)==w[i].hsh){
					f[i][j]=f[i-1][j-len-1];
				}
			}
			else{
				if(j-len>=0&&gthsh(j-len+1,j)==w[i].hsh){
					f[i][j]=sf[i-1][j-len];
				}
			}
		}
	}
}
int main()
{
	init();
	scanf("%s",s+1);
	solve_s();
	scanf("%d",&T);
	while(T--){
		scanf("%s",t+1);
		solve_t();
		solve_dp();
		if(f[w1][t1]) printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}
文章来源:https://blog.csdn.net/tanjunming2020/article/details/135825486
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。