1. 程式人生 > >[Luogu P2536] [BZOJ 1966] [AHOI2005]病毒檢測

[Luogu P2536] [BZOJ 1966] [AHOI2005]病毒檢測

洛谷傳送門

BZOJ傳送門

題目描述

科學家們在Samuel星球上的探險仍在繼續。非常幸運的,在Samuel星球的南極附近,探險機器人發現了一個巨大的冰湖!機器人在這個冰湖中搜集到了許多RNA片段運回了實驗基地。

科學家們經過幾個晝夜的研究,發現這些RNA片段中有許多是未知的病毒!

每個RNA片段都是由ACTG組成的序列。科學家們也總結出了Samuel星球上的“病毒模版片段”。一個模版片段是由A、C、T、G的序列加上萬用字元 *? 來表示。其中 * 的意思是可以匹配上 0

0 個或任意多個字元,而 ? 的意思是匹配上任意一個字母。

如果一個RNA片段能夠和“病毒模版片段”相匹配,那麼這個RNA片段就是未知的病毒。

例如,假設“病毒模版片段”為A*G?C。RNA片段:AGTCAGTGTC都是未知的病毒,而RNA片段AGTGC則不是病毒。

由於,機器人蒐集的這些RNA片段中除去病毒的其他部分都具有非常高的研究價值。所以科學家們希望能夠分辨出其中哪些RNA片段不是病毒,並將不是病毒的RNA片段運回宇宙空間站繼續進行研究。

科學家將這項任務交給了小聯。現在請你為小聯編寫程式統計哪些RNA片段不是病毒。

輸入輸出格式

輸入格式:

第一行有一個字串,由ACTG*? 組成。表示“病毒模版片段”。“病毒模版片段”的長度不超過 1000 1000 。第二行有一個整數 N N 0

< N < 500 0<N<500 ),表示機器人蒐集到的RNA片段的數目。隨後的 N N 行,每一行有一個字串,由ACTG組成,表示一個RNA片段。每個RNA片段的長度不超過 500 500 。注意:“病毒模版片段”和RNA片段的長度都至少為 1 1

輸出格式:

只有一行輸出,為整數 M M ,即不是病毒的RNA片段的數目。

輸入輸出樣例

輸入樣例#1:

A*G?C
3
AGTC
AGTGTC
AGTGC

輸出樣例#1:

1

說明

輸入中的RNA片段AGTGC不是病毒。

解題分析

資料範圍小, 直接 O ( N 2 ) O(N^2) 記憶化 D F S DFS 回答每組詢問即可。

不過如果最後一位是萬用字元的話可能比較麻煩, 需要特判, 直接在模板串和匹配串後面都加一個$即可。

程式碼如下:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 505
bool vis[MX][MX];
char mod[MX << 1], buf[MX];
int lena, lenb, num;
bool DFS(R int pa, R int pb)
{
    if (vis[pa][pb]) return false;
    if (pa == lena + 1 && pb == lenb + 1) return true;
    if (pa == lena + 1) return vis[pa][pb] = true, false;
    if (pb == lenb + 1) return vis[pa][pb] = true, false;
    if (isalpha(mod[pa]) || mod[pa] == '$')
    {
        if (mod[pa] == buf[pb]) return DFS(pa + 1, pb + 1);
        return vis[pa][pb] = true, false;
    }
    else
    {
        if (mod[pa] == '*')
        {
            for (R int i = pb; i <= lenb + 1; ++i)
            if (DFS(pa + 1, i)) return true;
            return vis[pa][pb] = true, false;
        }
        else
        {
            if (DFS(pa + 1, pb + 1)) return true;
            return vis[pa][pb] = true, false;
        }
    }
}
int main(void)
{
    scanf("%s", mod + 1); lena = std::strlen(mod + 1); ++lena; mod[lena] = '$';
    scanf("%d", &num);
    int ans = 0;
    W (num--)
    {
        scanf("%s", buf + 1);
        lenb = std::strlen(buf + 1); 
        ++lenb; buf[lenb] = '$';
        std::memset(vis, false, sizeof(vis));
        if (!DFS(1, 1)) ++ans;
    }
    printf("%d", ans);
}