首页 > 其他分享 >[CQOI2014]通配符匹配

[CQOI2014]通配符匹配

时间:2022-09-25 15:25:42浏览次数:50  
标签:匹配 int h3 ll 通配符 len tot CQOI2014 fo

好久没有做过字符串哈希的题,没想到竟然调了这么久。
首先我们可以母串根据?或者星号分为几段,这里有一个小技巧,可以给母串前面加一个?后面加一个a,然后在要匹配的串前后各加一个a
f[i][j]表示母串到了第i个,匹配的串到第j个位置。
那么有两种情况
第一种是?,f[i][j]=f[i-1][j-len]
第二种是星号,f[i][j]|=f[i-1][j-len-k]
然后用哈希判断相应字符串是否相等。
但是这样会TLE,我们需要对第二种情况进行优化。
设v[x],表示当*对应的长度为x的时候是否可以,每次更新一下即可。

点击查看代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#define fo(i,a,b) for (int (i)=(a);(i)<=(b);(i)++)
#define fd(i,b,a) for (int (i)=(b);(i)>=(a);(i)--)
using namespace std;
typedef unsigned long long ll;
const int N=1e5+5;
char s[N],t[N];
bool f[15][N],v[N];
ll h1[N],h2[N],h3[N],h4[N],p1[N],p2[N];
int n,l,tot,a[N],len,x[N],y[N],z[N];
ll num1,num2,num3,num4;
int sum[N];
bool pd(int x,int y,int z,int w){
	num1=h1[y]-h1[x-1]*p1[y-x+1];
	
	num2=h2[y]-h2[x-1]*p2[y-x+1];
	
	num3=h3[w]-h3[z-1]*p1[y-x+1];
	
	num4=h4[w]-h4[z-1]*p2[y-x+1];
	
	return (num1==num3 && num2==num4);
}
int main(){	
//	freopen("data.in","r",stdin);
	scanf("%s",s+1);
	l=strlen(s+1);
	
	p1[0]=1ll; p2[0]=1ll;
	fo(i,1,1e5){
		p1[i]=p1[i-1]*(ll)13;
		p2[i]=p2[i-1]*(ll)1331;
	}
	
	s[0]='?'; s[l+1]='a'; l++;
	
	fo(i,0,l) {
		if (s[i]=='?' || s[i]=='*')	{
			a[++tot]=i;
		}
	}
	
	fo(i,1,tot-1){
		x[i]=s[a[i]]=='*'? 2:1;
		y[i]=a[i+1]-a[i]-1;
		z[i]=a[i]+1;
	}
	x[tot]=s[a[tot]]=='*'? 2:1;
	y[tot]=l-a[tot];
	z[tot]=a[tot]+1;
	
	fo(i,1,l){
		if (s[i]=='*' || s[i]=='?') continue;
		h1[i]=h1[i-1]*(ll)13+(s[i]-'a'+1);  
		h2[i]=h2[i-1]*(ll)1331+(s[i]-'a'+1);
	}
	fo(i,1,tot) sum[i]=sum[i-1]+y[i];
//	fo(i,1,tot) printf("%d %d %d\n",x[i],y[i],z[i]);
	scanf("%d",&n);
	while (n--){
//		memset(h3,0,sizeof(h3));  // s[i]==* / ? h3[]=0
//		memset(h4,0,sizeof(h4));
		memset(f,0,sizeof(f));

		scanf("%s",t+1);
		len=strlen(t+1);
		
		t[0]='a'; t[len+1]='a'; len++;
		
		h3[0]=h4[0]=1;
	
		fo(i,1,len){
			h3[i]=h3[i-1]*(ll)13+(t[i]-'a'+1);  
			h4[i]=h4[i-1]*(ll)1331+(t[i]-'a'+1);
		}
		
//		printf("%d",pd(1,1,1,1));
//		return 0;
		f[1][y[1]]=pd(1,y[1],1,y[1]);
		if (!f[1][y[1]]) {
			puts("NO");  continue;
		}
		memset(v,0,sizeof(v));
	  	fo(i,y[1],len) v[i]=1;
		
		fo(i,2,tot) {
			fo(j,1,len){
				if (x[i]==1 && j-y[i]-1>=0) 
					f[i][j]|=f[i-1][j-y[i]-1]&&pd(z[i],z[i]+y[i]-1,j-y[i]+1,j);
				if (x[i]==2 && j>=y[i]) {
					f[i][j]|=v[j-y[i]]&&pd(z[i],z[i]+y[i]-1,j-y[i]+1,j);
				}
			}
			v[0]=0;
			fo(j,1,len) v[j]=v[j-1]|f[i][j];
		}
		if (f[tot][len]) puts("YES");
		else puts("NO");
	}
	return 0;
}

标签:匹配,int,h3,ll,通配符,len,tot,CQOI2014,fo
From: https://www.cnblogs.com/ganking/p/16727910.html

相关文章

  • C#教程 - 模式匹配(Pattern matching)
    更新记录转载请注明出处:2022年9月25日发布。2022年9月10日从笔记迁移到博客。常见匹配模式类型匹配模式(typepattern)属性匹配模式(propertypattern)匹配模式可以......
  • 力扣困难级别-10. 正则表达式匹配
    这道题昨天做了一下午,用动态规划、以及循环的方式也没弄出来,去评论去看了下,确实挺难的。晚上想到可以用做隐马尔科夫模型的思路,每次根据上一次的状态生成下一次的状态,最后......
  • suricata匹配从入门到精通(一)----suricata安装配置及使用
    https://blog.csdn.net/leeezp/article/details/126350975?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERa......
  • java eclipse 声明与期望的包不匹配
     只需要把需要执行的java拖动到src文件就可以执行了,不在期望的包里面 publicclasstest{publicstaticvoidmain(String[]args){ AAc=newAA();......
  • 正则,java匹配
    1.判断字符串中是否全为英文`booleanresult=str.matches("[a-zA-Z]+");//true:全文英文str.matches("[a-zA-Z0-9]+")//判断英文和数字`````2.提取字符串中所......
  • JQuery模糊匹配id
    在for循环div标签动态生成id,根据id的值显示或隐藏div标签,就可以用到模糊匹配。[属性名称]匹配包含给定属性的元素[att=value]匹配包含给定属性的元素(大小写区分)[att......
  • 【学习笔记】KMP字符串匹配
    字符串匹配——KMP算法给定两个字符串s1和s2,询问s2在s1中出现的位置(定义为出现时的第一个字符在s1中的位置)暴力枚举看到字符串匹配(如果你还不会KMP/Hash的话),八成是......
  • 新开源HTML5单文件网页版ACME客户端,可在线申请Let's Encrypt、ZeroSSL免费HTTPS多域名
    目录开源项目的起源项目地址使用方法第一步:选择Let'sEncrypt、ZeroSSL或其他证书颁发机构第二步:证书配置,填写域名第三步:完成域名所有权的验证第四步:下载保存证书PEM文件源......
  • 正则匹配替换字符串
    记录一下,正则匹配字符串例:leta='asdf1234<ahref="http://www.baidu.com">百度</a>qwer5678<aclass="123"href="http://www.google.com">google</a>'现在要给所......
  • P1559 运动员最佳匹配问题 题解
    本篇使用\(\text{KM}\)算法求解。对于\(\text{KM}\)算法步骤如下:首先要用邻接矩阵存二分图,然后用贪心算法初始化标杆,运用匈牙利算法找到完美匹配,如果找不到则修改标......