[bzoj3507 Cqoi2014]通配符匹配 (hash+DP)

传送门

Solution

显然用哈希233
设\(f[i][j]\)表示第i个通配符和当前第j个字符是否匹配
考虑两种通配符的特性,直接转移即可

Code

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define F(i,a,b) for(register int i=(a);i<=(b);i++)
using namespace std;
typedef unsigned long long ull;

const int N=200005,bas=233;
int n,len,tot;
bool f[20][N];
int cl[20];
ull da[N],hs[N],pw[N];
char s[N],ch[N];

int main() {
    pw[0]=1;F(i,1,N-1) pw[i]=pw[i-1]*bas;
    scanf("%s",s+1);len=strlen(s+1);s[++len]='?';
    F(i,1,len) {
        if(s[i]=='*'||s[i]=='?') cl[++tot]=i;
        da[i]=da[i-1]*bas+s[i];
    }
    scanf("%d",&n);
    while(n--) {
        memset(f,0,sizeof(f));f[0][0]=1;
        scanf("%s",ch+1);len=strlen(ch+1);ch[++len]='~';
        F(i,1,len) hs[i]=hs[i-1]*bas+ch[i];
        F(i,0,tot) {
            if(s[cl[i]]=='*') F(j,1,len) f[i][j]|=f[i][j-1];
            F(j,0,len) if(f[i][j]) {
                int l1=cl[i]+1,r1=cl[i+1]-1;
                int l2=j+1,r2=j+cl[i+1]-cl[i]-1;
//              cout<<l1<<" "<<r1<<" "<<l2<<" "<<r2<<endl;
                if(da[r1]-da[l1-1]*pw[r1-l1+1]!=hs[r2]-hs[l2-1]*pw[r2-l2+1]) continue;
                if(s[cl[i+1]]=='?') f[i+1][r2+1]=1;//,cout<<i+1<<" "<<r2+1<<endl;
                else f[i+1][r2]=1;//,cout<<i+1<<" "<<r2<<endl;
            }
        }
        if(f[tot][len]) puts("YES");
        else puts("NO");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Menteur-Hxy/p/9741114.html

时间: 2024-11-17 16:36:04

[bzoj3507 Cqoi2014]通配符匹配 (hash+DP)的相关文章

【BZOJ-3507】通配符匹配 DP + Hash

3507: [Cqoi2014]通配符匹配 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 372  Solved: 156[Submit][Status][Discuss] Description 几乎所有操作系统的命令行界面(CLI)中都支持文件名的通配符匹配以方便用户.最常见的通配符有两个,一个是星号(“”’),可以匹配0个及以上的任意字符:另一个是问号(“?”),可以匹配恰好一个任意字符.现在需要你编写一个程序,对于给定的文件名列表和一个包

bzoj 3507: [Cqoi2014]通配符匹配

Description 几乎所有操作系统的命令行界面(CLI)中都支持文件名的通配符匹配以方便用户.最常见的通配符有两个,一个是星号(“”’),可以匹配0个及以上的任意字符:另一个是问号(“?”),可以匹配恰好一个任意字符.现在需要你编写一个程序,对于给定的文件名列表和一个包含通配符的字符串,判断哪些文件可以被匹配. Input 第一行是一个由小写字母和上述通配符组成的字符串.第二行包含一个整数n,表示文件个数.接下来n行,每行为一个仅包含小写字母字符串,表示文件名列表. Output 输出n行

leetcode 44 通配符匹配(dp)

思路: 思路一: 利用两个指针进行遍历. 在代码里解释. 时间复杂度为:O(mn)O(mn)O(mn) 思路二: 动态规划 dp[i][j]表示s到i位置,p到j位置是否匹配! 初始化: dp[0][0]:什么都没有,所以为true    第一行dp[0][j],换句话说,s为空,与p匹配,所以只要p开始为*才为true    第一列dp[i][0],当然全部为False 动态方程: 如果(s[i] == p[j] || p[j] == "?") && dp[i-1][

L,uogu P3167 [CQOI2014]通配符匹配

Link 设\(f_{i,j}\)表示\(s\)从\(1\)到第\(i\)个通配符是否能匹配\(t_{1\sim j}\). 然后哈希一下再随便转移一下就好了. #include<cstdio> #include<cstring> using u64=unsigned long long; const int N=100007; u64 pw[N],hs[N],ht[N];char s[N],t[N];int f[12][N],pos[12]; int main() { int T

P3167 [CQOI2014]通配符匹配

吐槽 本来是去写AC自动机的,然后发现数据范围每个串100000,有100个串(???),连塞进trie树里都塞不进去,玩个鬼的AC自动机啊,tag不要乱打啊 最后拿字符串hash+爆搜一发搜过去了... 思路 挺恶心的搜索吧 考虑分段,按?号和*号分段,对于每段内的hash判断是否一致,*号和?号按题意处理即可 然后边界不要写挂就好了 代码 #include <cstdio> #include <cstring> #include <algorithm> using

bzoj3507【CQOI2014】通配符匹配

3507: [Cqoi2014]通配符匹配 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 309  Solved: 129 [Submit][Status][Discuss] Description 几乎所有操作系统的命令行界面(CLI)中都支持文件名的通配符匹配以方便用户.最常见的通配符有两个,一个 是星号(""'),可以匹配0个及以上的任意字符:另一个是问号("?"),可以匹配恰好一个任意字符. 现在需要你编写

[BZOJ3507]通配符匹配

3507: [Cqoi2014]通配符匹配 Time Limit: 10 Sec  Memory Limit: 128 MB Description 几乎所有操作系统的命令行界面(CLI)中都支持文件名的通配符匹配以方便用户.最常见的通配符有两个,一个是星号(""'),可以匹配0个及以上的任意字符:另一个是问号("?"),可以匹配恰好一个任意字符.现在需要你编写一个程序,对于给定的文件名列表和一个包含通配符的字符串,判断哪些文件可以被匹配. Input 第一行是一个

[LeetCode] Wildcard Matching 通配符匹配

Implement wildcard pattern matching with support for '?' and '*'. '?' Matches any single character. '*' Matches any sequence of characters (including the empty sequence). The matching should cover the entire input string (not partial). The function p

LeetCode(44): 通配符匹配

Hard! 题目描述: 给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配. '?' 可以匹配任何单个字符. '*' 可以匹配任意字符串(包括空字符串). 两个字符串完全匹配才算匹配成功. 说明: s 可能为空,且只包含从 a-z 的小写字母. p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *. 示例 1: 输入: s = "aa" p = "a" 输出: false 解释: "a"