zoukankan      html  css  js  c++  java
  • 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);
    }
    
  • 相关阅读:
    Android开发 listitem中采用倒计时
    fresco中设置占位/加载失败的图片 无效
    启动 angular-phonecat 项目时出现这玩意 。('The header content contains invalid characters');
    对于在Android Studio 的 build.gradle 中的默认applicationId 要不要写呢?
    Android-Cannot merge new index 66195 into a non-jumbo instruction的解决办法
    在eclipse 导入简单的Android studio 简单项目
    对于android浏览器的一些看法
    Error:Cause: org/gradle/api/publication/maven/internal/DefaultMavenFactory Android
    android 判断点击的位置是不是在指定的view上
    android studio(AS) Duplicate files copied in APK META-INF/NOTICE.txt
  • 原文地址:https://www.cnblogs.com/Karry5307/p/13894788.html
Copyright © 2011-2022 走看看