BZOJ3507. [CQOI2014] wildcard matching

Keywords: Asterisk

Description

Wildcard matching of filenames is supported in the command line interface (CLI) of almost all operating systems to facilitate users. The most common wildcards are two, one
Is an asterisk ("*"), which can match any character of 0 or more: the other is a question mark ("?" ), can match exactly one arbitrary character.
Now you need to write a program to determine which files can be matched for a given list of filenames and a string containing wildcards.

Input

The first line is a string of lowercase letters and the above wildcards.
The second line contains an integer n representing the number of files.
Next n lines, each line contains a lowercase character string, representing a list of filenames.

Output

Output n lines, each line "YES" or "NO", indicating whether the corresponding file can be matched by wildcards.

Sample Input

*aca?ctc
6
acaacatctc
acatctc
aacacatctc
aggggcaacacctc
aggggcaacatctc
aggggcaacctct

Sample Output

YES
YES
YES
YES
YES
NO

HINT

For 100% of data
String length not more than 1 00000
1 <=n<=100
No more than 10 wildcards

Title Solution

There is a very important thing about the topic,
There are no more than 10 wildcards.

Consider an obvious approach,
Set fi,j to indicate whether one string matches i and the other string matches J.
As long as the judgment will? As for all characters, * special processing is OK.

But this time complexity is unacceptable,
Just change the status a little bit:
Set fi,j to indicate whether a string matches the ith wildcard, matches J, and is legal.
According to the wildcard character, the original string is divided into several parts, and then matched one by one.
hash is used to determine whether two strings are equal.

code

#pragma GCC optimize(2)
#pragma G++ optimize(2)
#include<queue>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#define ll long long
#define ull unsigned long long
#define N 100003
#define M 102
#define db double
#define P putchar
#define G getchar
#define mo 13890604
#define zm 19260817
using namespace std;
char ch;
void read(int &n)
{
    n=0;
    ch=G();
    while((ch<'0' || ch>'9') && ch!='-')ch=G();
    ll w=1;
    if(ch=='-')w=-1,ch=G();
    while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
    n*=w;
}

db max(db a,db b){return a>b?a:b;}
db min(db a,db b){return a<b?a:b;}
ll abs(ll x){return x<0?-x:x;}
ll sqr(ll x){return x*x;}
void write(ll x){if(x>9) write(x/10);P(x%10+'0');}

char s[N],t[N];
int len,n,pos[13],cnt;
ull s1[N],s2[N],p[N];
bool f[13][N];

ull get1(int x,int y)
{
    return x>y?0:s1[y]-s1[x-1]*p[y-x+1];
}

ull get2(int x,int y)
{
    return x>y?0:s2[y]-s2[x-1]*p[y-x+1];
}

int main()
{
    p[0]=1;
    for(int i=1;i<N;i++)
        p[i]=p[i-1]*zm;

    scanf("%s",s+1);
    len=strlen(s+1);

    for(int i=1;i<=len;i++)
    {
        if(s[i]<'a' || s[i]>'z')pos[++cnt]=i;
        s1[i]=s1[i-1]*zm+s[i];
    }
    s[pos[++cnt]=++len]='?';

    read(n);
    while(n--)
    {
        scanf("%s",t+1);
        len=strlen(t+1);
        t[++len]='!';
        for(int i=1;i<=len;i++)
            s2[i]=s2[i-1]*zm+t[i];

        memset(f,0,sizeof(f));
        f[0][0]=1;
        for(int i=0;i<cnt;i++)
        {
            if(s[pos[i]]=='*')
            {
                for(int j=1;j<=len;j++)
                    if(f[i][j-1])f[i][j]=1;
            }
            for(int j=0;j<=len;j++)
                if(f[i][j] && get1(pos[i]+1,pos[i+1]-1)==get2(j+1,j+pos[i+1]-pos[i]-1))
                {
                    if(s[pos[i+1]]=='?')f[i+1][j+pos[i+1]-pos[i]]=1;
                        else f[i+1][j+pos[i+1]-pos[i]-1]=1;
                }
        }
        if(f[cnt][len])P('Y'),P('E'),P('S');
            else P('N'),P('O');
        P('\n');
    }
}

Posted by alpine on Thu, 30 Apr 2020 06:19:54 -0700