• [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
    ",ans);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    文件上传按钮样式定制
    消除2个按钮之间1px细节引起的冲突
    css 实用代码汇总
    除掉inline-block 间距
    SQL Server 创建索引的 5 种方法
    百度API从经纬度坐标到地址的转换服务
    百度地图API简单应用——1.根据地址查询经纬度
    极光API推送 (v3 版本)
    简单快捷地测试 JPush API
    使用极光推送(www.jpush.cn)向安卓手机推送消息【服务端向客户端主送推送】C#语言
  • 原文地址:https://www.cnblogs.com/mastervan/p/14598426.html
Copyright © 2020-2023  润新知