zoukankan      html  css  js  c++  java
  • [AHOI2005] 病毒检测

    给定一个模板串,里面带有 * (可以匹配任意一段可以为空的串)和 ? (可以匹配任意一个字母),然后给定 (n) 个询问串,问有多少询问串不能匹配。(n leq 500, len leq 1000)

    Solution

    对所有询问串建立字典树,然后考虑一个 BFS 过程,状态表示为 ((i,j)),即模板串正要处理第 (i) 个字符,而字典树上走到了 (j) 位置,然后讨论模板串的这一位来转移

    • 如果模板串的这一位是字母,则模板串走一位,结点走对应字母的转移边
    • 如果模板串的这一位是 ?,则模板串走一位,结点走所有字母的转移边
    • 如果模板串的这一位是 *,则
      • 模板串不走,结点走所有字母的转移边
      • 模板串走一位,结点不走

    这样就涵盖了所有的转移方法

    每走到一个节点,如果 (i=n+1),我们就把 (j) 这个节点打上标记

    最后统计所有的打标记的结点中包含了多少个询问串的结束位置即可

    为了优化效率,当一个点被打过标记后,下次再走到这个点就直接跳过;走过的状态搞个哈希表记录一下,再走时候直接弹掉

    用了双哈希

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 1000005;
    int n,m,str[N],ch[N][4],fg[N],val[N],ind=1;
    char buf[N];
    const int mod1 = 492837465, mod2 = 400000007;
    bitset <mod1> b1;
    bitset <mod2> b2;
    int gen1(int i,int j) {
        return (1ll*j*31415926+i)%mod1;
    }
    int gen2(int i,int j) {
        return (1ll*j*998244353+i)%mod2;
    }
    
    struct status {int i,j;};
    
    int tr(char c) {
        if(c=='A') return 0;
        if(c=='C') return 1;
        if(c=='T') return 2;
        if(c=='G') return 3;
    }
    
    signed main() {
        ios::sync_with_stdio(false);
        scanf("%s",buf+1);
        n=strlen(buf+1);
        for(int i=1;i<=n;i++) {
            if(buf[i]=='A') str[i]=0;
            if(buf[i]=='C') str[i]=1;
            if(buf[i]=='T') str[i]=2;
            if(buf[i]=='G') str[i]=3;
            if(buf[i]=='?') str[i]=4;
            if(buf[i]=='*') str[i]=5;
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++) {
            scanf("%s",buf+1);
            int len=strlen(buf+1);
            int p=1;
            for(int j=1;j<=len;j++) {
                int x=tr(buf[j]);
                if(ch[p][x]==0) ch[p][x]=++ind;
                p=ch[p][x];
            }
            val[p]++;
        }
        queue <status> q;
        q.push({1,1});
        while(q.size()) {
            status p=q.front();
            q.pop();
            int i=p.i, j=p.j;
            if(b1[gen1(i,j)]&&b2[gen2(i,j)]) continue;
            b1[gen1(i,j)]=1;
            b2[gen2(i,j)]=1;
            if(i==n+1) {
                fg[j]=1;
            }
            else if(!fg[j] && j) {
                if(str[i]<4) {
                    q.push({i+1,ch[j][str[i]]});
                }
                if(str[i]==4) {
                    if(ch[j][0]) q.push({i+1,ch[j][0]});
                    if(ch[j][1]) q.push({i+1,ch[j][1]});
                    if(ch[j][2]) q.push({i+1,ch[j][2]});
                    if(ch[j][3]) q.push({i+1,ch[j][3]});
                }
                if(str[i]==5) {
                    if(ch[j][0]) q.push({i,ch[j][0]});
                    if(ch[j][1]) q.push({i,ch[j][1]});
                    if(ch[j][2]) q.push({i,ch[j][2]});
                    if(ch[j][3]) q.push({i,ch[j][3]});
                    q.push({i+1,j});
                }
            }
        }
        int ans=0;
        for(int i=1;i<=ind;i++) ans+=fg[i]*val[i];
        cout<<m-ans;
    }
    
    
  • 相关阅读:
    Crazyflie 2.0 System Architecture
    HDU 4856 Tunnels(BFS+状压DP)
    scp报错:Host key verification failed. REMOTE HOST IDENTIFICATION HAS CHANGED!
    HDU 4175 Class Schedule (暴力+一点dp)
    正則表達式
    匿名訪问之(一)web application级别
    Android UI布局之TableLayout
    cocos2d-x-3.3rc2-003 cocos中的引用计数和自己主动释放池
    一步一步跟我学习hadoop(7)----hadoop连接mysql数据库运行数据读写数据库操作
    hdu Swipe Bo(bfs+状态压缩)错了多次的题
  • 原文地址:https://www.cnblogs.com/mollnn/p/12445027.html
Copyright © 2011-2022 走看看