51nod 1532 带可选字符的多字符串匹配(位运算)

题意:

有一个文本串,它的长度为m (1 <= m <= 2000000),现在想找出其中所有的符合特定模式的子串位置。
符合特定模式是指,该子串的长度为n (1 <= n <= 500),并且第i个字符需要在给定的字符集合Si中。
因此,描述这一特定模式,共需要S1,S2,...,Sn这n个字符集合。每个集合的大小都在1~62之间,其中的字符只为数字或大小写字母。

 

题解:

很类似之前做过的一道cf的题目,利用shift-and算法优化到nm/64的复杂度

每一次匹配的结果实际上就是(v<<1)&Mask[S[i]]的结果(有点像卷积)

然后一步步左移就可以了。

还有一个比较坑的地方是会卡cin(有些奇怪的字符)

需要用gets和getchar来做。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <bitset>
using namespace std;
const int maxn = 2000050;
typedef long long LL;
int tab[250];
char S[maxn], T[505];
bitset<505> v, Mask[64];
int L, n, x;
void pre(){
    memset(tab, 1, sizeof(tab));
    int tot = 0;
    for(int i = 'a'; i <= 'z'; i++) tab[i] = tot++;
    for(int i = 'A'; i <= 'Z'; i++) tab[i] = tot++;
    for(int i = '0'; i <= '9'; i++) tab[i] = tot++;
}
int main()
{
    pre();
    while(gets(S)){
        L = strlen(S);
        cin>>n;
        for(int i = 0; i <= 62; i++) Mask[i].reset(); v.reset();
        for(int i = 1; i <= n; i++){
            scanf("%d", &x);
            cin>>T;
            for(int j = 0; j < x; j++) Mask[tab[T[j]]][i] = 1;
        }
        int fail = 1;
        v[0] = 1;
        for(int i = 0; i < L; i++){
            if(S[i] < 200 && tab[S[i]] < 70) v = (v<<1)&Mask[tab[S[i]]]; else v.reset();
            v[0] = 1;
            if(v[n] == 1){
                fail = 0;
                printf("%d\n", i-n+2);
            }
        }
        if(fail) printf("NULL\n");
        getchar();
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/Saurus/p/7648021.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值