[BZOJ3507]通配符匹配

3507: [Cqoi2014]通配符匹配

Time Limit: 10 Sec  Memory Limit: 128 MB

Description

几乎所有操作系统的命令行界面(CLI)中都支持文件名的通配符匹配以方便用户。最常见的通配符有两个,一个
是星号(“”’),可以匹配0个及以上的任意字符:另一个是问号(“?”),可以匹配恰好一个任意字符。
现在需要你编写一个程序,对于给定的文件名列表和一个包含通配符的字符串,判断哪些文件可以被匹配。

Input

第一行是一个由小写字母和上述通配符组成的字符串。
第二行包含一个整数n,表示文件个数。
接下来n行,每行为一个仅包含小写字母字符串,表示文件名列表。

Output

输出n行,每行为“YES”或“NO”,表示对应文件能否被通配符匹配。

Sample Input

*aca?ctc

6

acaacatctc

acatctc

aacacatctc

aggggcaacacctc

aggggcaacatctc

aggggcaacctct

Sample Output

YES

YES

YES

YES

YES

NO

HINT

对于1 00%的数据
  ·字符串长度不超过1 00000
  ·  1 <=n<=100
  ·通配符个数不超过10

题解:

考场打暴力打炸了……

不过在后来改题的时候我发现了暴力思路的一个大问题……我们还是直接讲正解吧

题目给的通配符有2种,一种是’*’,它可以伸展;一种是‘?’,它的长度固定;

不难发现,给我们的处理带来难度的是‘*‘,因为他的长度不确定;

但转念一想,如果除了*,其他的都能匹配,那*也就能匹配了.

注意到通配符个数<=10,那么我们可以先按照*,把原串分成一些包含‘?‘和字母的段.

而对于每一段,只要其中的所有小字符串成功匹配,并且符合‘?‘对长度的要求,这一段就匹配成功了

所以我们再在每一段里,按照‘?‘再分为几小块只含字母的串,并且分别求出hash值;同时求出文本串的hash值.

在匹配的时候,对于某一段,枚举起点,看在这一段在哪里可以匹配.

由于对于段间的枚举,影响因素只有*,所以匹配点肯定越靠前越好,因此这里可以贪心,即找到最靠前的匹配点即可停止.

而对于段内比较,利用刚才求的hash值比较就好.

代码见下:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<string>
 5 using namespace std;
 6 typedef unsigned long long LL;
 7 const int N=100010;
 8 const int mod1=9901;
 9 int n,lens,len,cnt,cnt1[20];
10 char s[N],text[N];
11 LL block[20][20],h[N],mi[N];
12 int l[20][20],num[20];
13 inline LL g_hash(int l,int r){return h[r]-h[l-1]*mi[r-l+1];}
14 inline bool match(int i,int k)
15 {
16     for(int j=0;j<=num[k];j++)
17     {
18         if(l[k][j]==0){i++;continue;}
19         if(block[k][j]!=g_hash(i,i+l[k][j]-1))return 0;
20         i+=l[k][j]+1;
21     }
22     return 1;
23 }
24 bool judge()
25 {
26     if(!cnt)
27     {
28         if(len!=lens)return 0;
29         for(int i=1;i<=len;i++)
30             if(s[i]!=text[i]&&s[i]!=‘?‘)return 0;
31         return 1;
32     }
33     if(len<(cnt1[1]-1)+(lens-cnt1[cnt]))return 0;
34     for(int i=1;i<cnt1[1];i++)if(s[i]!=text[i]&&s[i]!=‘?‘)return 0;
35     for(int i=lens,j=len;i>cnt1[cnt];i--,j--)if(s[i]!=text[j]&&s[i]!=‘?‘)return 0;
36     for(int i=1;i<=len;i++)
37         h[i]=h[i-1]*mod1+text[i];
38     int i=cnt1[1],line=len-(lens-cnt1[cnt])+1;
39     for(int k=2;k<=cnt;k++)
40     {
41         for(;i<=line;i++)
42             if(match(i,k))break;
43         i+=cnt1[k]-cnt1[k-1]-1;
44         if(i>line)return 0;
45     }
46     return 1;
47 }
48 int main()
49 {
50     scanf("%s",s+1);lens=strlen(s+1);
51     mi[0]=1;for(int i=1;i<=lens;i++)mi[i]=mi[i-1]*mod1;
52     for(int i=1;i<=lens;i++)
53         if(s[i]==‘*‘)cnt1[++cnt]=i;
54     for(int i=2;i<=cnt;i++)
55     {
56         num[i]=0;
57         for(int j=cnt1[i-1]+1;j<cnt1[i];j++)
58         {
59             if(s[j]==‘?‘){num[i]++;continue;}
60             l[i][num[i]]++;
61             block[i][num[i]]=block[i][num[i]]*mod1+s[j];
62         }
63     }
64     scanf("%d",&n);
65     for(int i=1;i<=n;i++)
66     {
67         scanf("%s",text+1);len=strlen(text+1);
68         if(judge())printf("YES\n");
69         else printf("NO\n");
70     }
71 }

BZOJ3507

时间: 2024-10-24 05:12:20

[BZOJ3507]通配符匹配的相关文章

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

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

bzoj3507【CQOI2014】通配符匹配

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

WildcardMatching和Regex,通配符匹配和正则表达式匹配

WildcardMatching:通配符匹配 算法分析: 1. 二个指针i, j分别指向字符串.匹配公式. 2. 如果匹配,直接2个指针一起前进. 3. 如果匹配公式是*,在字符串中依次匹配即可. 注意记录上一次开始比较的位置 Implement wildcard pattern matching with support for '?' and '*' '?' Matches any single character. '*' Matches any sequence of character

[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

bzoj 3507: [Cqoi2014]通配符匹配

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

LeetCode(44): 通配符匹配

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

(Java) LeetCode 44. Wildcard Matching —— 通配符匹配

Given an input string (s) and a pattern (p), 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 enti

LeetCode 44. 通配符匹配

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

LeetCode 44. 通配符匹配(Wildcard Matching)

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