• [BFS]luogu P2536 [AHOI2005]病毒检测


    题面

    https://www.luogu.com.cn/problem/P2536

    分析

    考虑建一个像trie的东西,即向下一个节点连代表字母的边

    那么对于 AGCT 就直接向下一个节点连边

    对于 ? 则可以向下一个节点连所有字母的边

    对于 * ,我们采用对通配符的惯用操作,向自己连所有字母的边,即构造自环,表示匹配的时候可以是任意串

    那么匹配的时候,在匹配串里正常移动,模式串里BFS,但是会T

    考虑优化,发现对于匹配串的当前位置转移到下一个位置,在模式串中的每个点只能到达一次

    所以用滚动队列跑BFS,每次扩展状态的时候标记一个 added 数组即可,记得清空

    同时跑到匹配串和模式串的结尾则是一个未知病毒

    代码

    #include <iostream>
    #include <cstdio>
    #include <queue>
    #include <cstring>
    using namespace std;
    const int N=510;
    struct Graph {
        int v,w,nx;
    }g[8*N];
    int cnt,list[2*N],gcnt;
    int n,m,ans;
    char s[2*N];
    bool added[2*N];
    
    void Add(int u,int v,int w) {g[++cnt]=(Graph){v,w,list[u]};list[u]=cnt;}
    
    void BFS() {
        queue<int> q[2];int e=0;
        while (!q[0].empty()) q[0].pop();while (!q[1].empty()) q[1].pop();
        q[e].push(0);
        for (int j=1;j<m;j++) {
            memset(added,0,sizeof added);
            while (!q[e].empty()) {
                int u=q[e].front();q[e].pop();
                for (int i=list[u];i;i=g[i].nx)
                    if (g[i].w==s[j]&&!added[g[i].v]) added[g[i].v]=1,q[e^1].push(g[i].v);
            }
            e^=1;
        }
        while (!q[e].empty()) {
            int u=q[e].front();q[e].pop();
            for (int i=list[u];i;i=g[i].nx)
                if (g[i].w==s[m]&&g[i].v==gcnt) return;
        }
        ans++;
    }
    
    int main() {
        scanf("%s",s+1);m=strlen(s+1);
        for (int i=1;i<=m;i++) {
            switch (s[i]) {
                case '?':{
                    Add(gcnt,gcnt+1,'A');Add(gcnt,gcnt+1,'G');Add(gcnt,gcnt+1,'C');Add(gcnt,gcnt+1,'T');gcnt++;
                    break;
                }
                case '*':{
                    Add(gcnt,gcnt,'A');Add(gcnt,gcnt,'G');Add(gcnt,gcnt,'C');Add(gcnt,gcnt,'T');
                    break;
                }
                default:{
                    Add(gcnt,gcnt+1,s[i]);gcnt++;
                    break;
                }
            }
        }
        scanf("%d",&n);
        for (int i=1;i<=n;i++) scanf("%s",s+1),m=strlen(s+1),BFS();
        printf("%d\n",ans);
    }
    View Code
  • 相关阅读:
    今日总结
    今日总结
    今日总结
    今日总结
    今日总结
    java自学
    java自学
    Java自学
    Java自学
    java自学
  • 原文地址:https://www.cnblogs.com/vagari/p/14598426.html
Copyright © 2020-2023  润新知