• Luogu P2536 [AHOI2005]病毒检测


    题意

    给一个有通配符的模式串和 (n) 个文本串,其中 ? 可以匹配任意字符,* 可以匹配 (0) 或任意多个字符,求 (n) 个文本串中无法与模式串匹配的数量。

    ( exttt{Data Range:}1leq nleq 500)

    题解

    非确定性有限状态决策自动机。

    首先考虑对模式串建一个自动机。对于每一位我们可以抽象成一个节点,整个字符串可以抽象成一个转移图。在匹配的过程中,如果能够走到这个节点上来就说明能够与这个位置的前缀相匹配。这里需要讨论一下:

    • 如果模式串的某一位为字母,那么将这一位的状态向下一位的状态连这个字母的边,也就是说只有这个字母能从这一位转移到下一位。

    • 如果模式串的某一位为 ?,那么任何字母进来都能匹配上,也就是说将这一位的状态向下一位的状态连所有字母的边。

    • 如果模式串的某一位为 *,这里是个小 trick,也就是说可以匹配任意长度的串,那就连个自环就可以了。

    然后,对于匹配的话,从初始状态开始走,如果能够走到结束状态那么则匹配成功。

    代码非常好写,跑得也很快。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef int ll;
    typedef long long int li;
    const ll MAXN=1e3+51;
    struct Node{
        ll isEnd;
        vector<ll>nxt[4];
    };
    Node x[MAXN];
    vector<ll>s,nxt;
    ll n,len,tot,c,flg,res;
    ll mp[128],vis[MAXN];
    char ch[MAXN];
    inline ll read()
    {
        register ll num=0,neg=1;
        register char ch=getchar();
        while(!isdigit(ch)&&ch!='-')
        {
            ch=getchar();
        }
        if(ch=='-')
        {
            neg=-1;
            ch=getchar();
        }
        while(isdigit(ch))
        {
            num=(num<<3)+(num<<1)+(ch-'0');
            ch=getchar();
        }
        return num*neg;
    }
    inline void match()
    {
        s.clear(),s.push_back(1);
        for(register int i=1;i<=len;i++)
        {
            nxt.clear(),flg=0;
            for(register int j=1;j<=tot;j++)
            {
                vis[j]=0;
            }
            for(register int j=0;j<s.size();j++)
            {
                for(register int k=0;k<x[s[j]].nxt[mp[ch[i]]].size();k++)
                {
                    if((c=x[s[j]].nxt[mp[ch[i]]][k])&&!vis[c])
                    {
                        vis[c]=1,nxt.push_back(c),flg|=x[c].isEnd;
                    }
                }
            }
            s=nxt;
        }
        res+=1-flg;
    }
    int main()
    {
        scanf("%s",ch+1),len=strlen(ch+1),tot=1,memset(mp,-1,sizeof(mp));
        mp['A']=0,mp['G']=1,mp['C']=2,mp['T']=3;
        for(register int i=1;i<=len;i++)
        {
            if(mp[ch[i]]!=-1)
            {
                x[tot].nxt[mp[ch[i]]].push_back(tot+1),tot++;
                continue;
            }
            if(ch[i]=='?')
            {
                x[tot].nxt[0].push_back(tot+1),x[tot].nxt[1].push_back(tot+1);
                x[tot].nxt[2].push_back(tot+1),x[tot].nxt[3].push_back(tot+1);
                tot++;
                continue;
            }
            if(ch[i]=='*')
            {
                x[tot].nxt[0].push_back(tot),x[tot].nxt[1].push_back(tot);
                x[tot].nxt[2].push_back(tot),x[tot].nxt[3].push_back(tot);
                continue;
            }
        }
        x[tot].isEnd=1,n=read();
        for(register int i=0;i<n;i++)
        {
            scanf("%s",ch+1),len=strlen(ch+1),match();
        }
        printf("%d
    ",res);
    }
    
  • 相关阅读:
    常见数据结构使用场景
    Java与算法之(4)
    Java与算法之(3)
    Java与算法之(2)
    Java与算法之(1)
    Maven适配多种运行环境的打包方案
    从头开始基于Maven搭建SpringMVC+Mybatis项目(4)
    从头开始基于Maven搭建SpringMVC+Mybatis项目(3)
    从头开始基于Maven搭建SpringMVC+Mybatis项目(2)
    从头开始基于Maven搭建SpringMVC+Mybatis项目(1)
  • 原文地址:https://www.cnblogs.com/Karry5307/p/13894788.html
Copyright © 2020-2023  润新知