zoukankan      html  css  js  c++  java
  • HDU 5716 带可选字符的多字符串匹配(ShiftAnd)

    【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=5716

    【题目大意】

      给出一个字符串,找出其中所有的符合特定模式的子串位置,符合特定模式是指,该子串的长度为n,并且第i个字符需要在给定的字符集合Si

     

    【题解】

      这种串与字符集的匹配称为柔性字符串匹配,采用ShiftAnd的匹配方法。

      bt[i]表示字符i允许在哪些位置上出现,我们将匹配成功的位置保存在dp中,那么就可以用dp[i]=dp[i-1]<<1&bt[s[i]]来更新答案了

      利用滚动数组和bitset可以来优化这样的运算,当一个位置的匹配在更新的过程中没有丢失,即始终在特定模式中直到定长,那么这个位置就是成功匹配位

      复杂度为O(nm/64)

     

    【代码】

    #include <cstdio>
    #include <bitset>
    #include <cstring>
    using namespace std;
    const int M=510,N=2000010,L=65,U=256;
    bitset<M> dp[2],bt[U];
    int n,m,id[U],cnt,l;
    char s[N],t[L];
    void init(){
        cnt=0;
        for(int i='0';i<='9';i++)id[i]=++cnt;
        for(int i='A';i<='Z';i++)id[i]=++cnt;
        for(int i='a';i<='z';i++)id[i]=++cnt;
    }
    void ShiftAnd(int n,int m){
        int cur=1,f=0;
        dp[0].reset(); dp[0].set(0);
        for(int i=1;i<=n;i++,cur^=1){
            dp[cur]=dp[cur^1]<<1&bt[id[s[i]]];
            dp[cur].set(0);
            if(dp[cur][m])printf("%d
    ",i-m+(f=1));
        }if(!f)puts("NULL");
    }
    int main(){
        init();
        while(gets(s+1)){
            n=strlen(s+1);
            scanf("%d",&m);
            for(int i=1;i<=cnt;i++)bt[i].reset();
            for(int i=1;i<=m;i++){
                scanf("%d %s",&l,t);
                for(int j=0;j<l;j++)bt[id[t[j]]].set(i);
            }ShiftAnd(n,m);gets(s);
        }return 0;
    }
    

      

  • 相关阅读:
    Qt 模态对话框不模态的问题
    Qt layout更新控件的问题
    javamail中使用一些问题的解决方案
    mysql too many connection解决方法
    hibernate的三种状态
    hibernate的几种主键
    hibernate的crud操作
    ajax简单校验用户名是否存在
    json的简单使用
    ajax读取服务器文本
  • 原文地址:https://www.cnblogs.com/forever97/p/hdu5716.html
Copyright © 2011-2022 走看看