首页 > 其他分享 >match 题解

match 题解

时间:2023-02-25 09:33:12浏览次数:26  
标签:匹配 int 题解 模式 字符串 match define

题面

题目描述

一个匹配模式是由一些小写字母和问号组成的一个字符串。当一个由小写字母组成的字符串 \(s\),长度和匹配模式长度相同,并且在对应的每一位都相等或模式串相应位置是问号,则称字符串 \(s\) 与这个模式相匹配。例如:abca?c匹配,但不与a?babc?相匹配。

现给你 \(n\) 个长度相同的模式串,恰好与其中 \(m\) 个模式串相匹配的字符串有多少个?

输入格式

第一行两个整数,\(n\) 和 \(m\),含义如题目描述。

接下来 \(n\) 行,每行输入一个只含有小写字母和字符?的字符串,保证所有字符串均等长,表示 \(n\) 个模式串。

输出格式

一个整数,为题目描述中问题的结果 \(\mod 1000003\)。

样例输入1

2 2
a?
?b

样例输出1

1

样例输入2

1 1
?????

样例输出2

881343

说明/提示

\(1 \leq n,m \leq 15\),字符串长度小于 \(50\)。

题解

看到 \(n,m\) 的范围以及求方案数果断想到状压 dp。

我们设 \(f_{i,s}\) 表示当前匹配到第 \(i\) 位,状态为 \(s\) 的方案数。\(s\) 为一个长度为 \(n\) 的二进制数,记录当前与 \(n\) 个串的匹配状态。

我们再预处理一个 \(g\) 数组,\(g_{i,j}\) 表示在模式串的第 \(i\) 位是字母 \(j\) 时,能匹配的模式串的位置,换句话说,第 \(i\) 位 是 \(j\) 或问号的模式串的位置,仍然可以使用状压存储。

由于有恰好 \(m\) 个匹配的限制,我们倒序处理。

设模式串长为 \(l\)。

我们先对全部匹配完成状态 \(f_{l+1,j}\) 赋初始值,遍历每种可能的 \(j\),如果 \(j\) 中恰好有 \(m\) 个 \(1\),那么 \(f_{l+1,j}=1\),否则 \(f_{l+1,j}=0\)

随后我们从 \(l\) 到 \(1\) 遍历 \(i\),则显然有转移如下:

\[f_{i,j}=\sum\limits_{k=0}^{25}f_{i+1,j \operatorname{and} g_{i,k}} \]

暴力转移即可。复杂度 \(O(l \times 2^n \times 26)\)

code:

#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define debug cout<<"DEBUG"<<endl;
#define pb push_back
#define pii pair<int,int>
#define vi vector<int>
#define imp map<int,int>
using namespace std;
const int N=20,M=100,mod=1e6+3;
int n,m,l;
ll g[M][30],f[M][50000];
char c[N][M];

int main(){
	freopen("match.in","r",stdin);
	freopen("match.out","w",stdout);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>c[i]+1;
	}
	l=strlen(c[1]+1);
	for(int i=1;i<=l;i++){
		for(int j=0;j<26;j++){
			g[i][j]=0;
			for(int k=1;k<=n;k++){
				if(c[k][i]=='?'||c[k][i]==j+'a'){
					g[i][j]|=(1<<(k-1));
				}
			}
		}
	}
	for(int i=l+1;i>0;i--){
		for(int j=0;j<(1<<n);j++){
			if(i==l+1){
				int res=0;
				for(int k=1;k<=n;k++){
					if(j&(1<<(k-1))){
						res++;
					}
				}
				if(res==m){
					f[i][j]=1;
				}else{
					f[i][j]=0;
				}
			}else{
				f[i][j]=0;
				for(int k=0;k<26;k++){
					f[i][j]+=f[i+1][j&g[i][k]];
					f[i][j]%=mod;
				}
			}
		}
	}
	cout<<f[1][(1<<n)-1]<<endl;
	return 0;
}

标签:匹配,int,题解,模式,字符串,match,define
From: https://www.cnblogs.com/victoryang-not-found/p/17153747.html

相关文章

  • 题解 Codeforces 1746F Kazaee
    题意给定长度为\(n\)的数组\(a\),和\(q\)次操作,支持:给定\(i,x\),修改\(a_i\)为\(x\)给定\(l,r,k\),查询\([l,r]\)中是否每个数的出现次数都是\(k\)的倍数......
  • 题解 LOJ P2393 「JOISC 2017 Day 2」门票安排
    题意咕咕咕。题解这题太神了,无限膜拜p_b_p_b,搬运一波题解。首先考虑二分。题意等价于选一些区间进行反转。首先注意到反转的区间两两有交,不然不反转一定更优。设反转......
  • P8822 [传智杯#3 初赛] 课程报名 题解
    题目传送门题目大意有一种课程,初始定价为\(v\)元;每报名\(m\)个学员,课程的定价就要提升\(a\)元,一共有\(n\)个学员报名。解题思路因为一共有\(n\)个学员报名,所......
  • P8717 [蓝桥杯 2020 省 AB2] 成绩分析 题解
    题目传送门题目大意计算\(n\)个人考试的最高分、最低分和平均分。解题思路输入\(n\)个人成绩的同时,计算最大值,最小值和总数。再将总数除以\(n\)算出平均值并保......
  • AtCoder Beginner Contest 285 A-F 题解
    比赛链接A-EdgeChecker2判断y==2x||y==2x+1即可。点击查看代码#include<cstdio>#include<algorithm>#include<cstring>usingnamespacestd;inta......
  • AtCoder Beginner Contest 283 A-F 题解
    A-Power快速幂板子点击查看代码#include<cstdio>#include<algorithm>usingnamespacestd;#defineintlonglongintn,m;intqpow(inta,intb){ intr......
  • CF837D题解
    CF837D题解没有用的话今天晚上在CF题库里随便选题选的,感觉还不错的题。昨天就开始停自习了,但是一直在摆烂(悲,自从上个学期就这样了,非常怀念一年前的机房,风清气正,大家都......
  • THUPC2019 令人难以忘记的题目名称 题解
    首先感性感觉这个东西是比较有循环节的,但这是后话。最后几步一定是差分相同->每个数相同->全为0。不平凡地猜想差分\(k\)次全\(0\)等价于可以\(k\)步胜利。假设......
  • Universial Cup 题解
    开始瞎做题了全部都写了简要题意,题解默认折叠,可以来做做(?UniversialCup官网The1stUniversalCup比赛名称&题解链接题解包含题目QOJlinkCodeforcesGymLin......
  • 题解 北大集训2018 点分治
    题意给定\(n\)个点的树,求点分治方案数,对\(10^9+7\)取模。两种方案不同当且仅当点分树不同。\(1\leqn\leq5000\)题解考虑怎样合并两个点分治方案。如果我们有......