hdu5972 快速匹配bitset优化(shiftand算法)2016ACM/ICPC亚洲区大连站

题意:

给你N位数,接下来有N行,第i行先输入n,表示这个数的第i 位上可以在接下来的n个数中挑选,然后i 行再输n个数。

然后输入需要匹配的母串,让你输出母串中有多少个可行的N位子串。

思路:
字符串匹配么,

 N (1 ≤ N ≤ 1000)

s最长为5 * 10^6

思路1:int a[1000][10]; 用它来存,看都不用看了,数据量太大,直接弃用。

思路2:KMP,也不行,因为匹配失败后,不知道匹配到了什么地方,也不行。

改进:a[1000][10]桶装,

先memset(a,0,sizeod(a));

然后

a[1][0] = a[1][9] = a[1][1] = 1;

a[2][5] = a[2][7] = 1;

a[3][2] = a[3][5] = 1;

a[4][4] = a[4][5] = 1;

结果?TLE

很无奈,怎么办?

使用bitset<N> b[10];

bitset是什么?

bitset可以看作二进制位的容器,并能提供位的相关操作函数。

基本操作:

bitset &set():位容器的所有位置1

bitset &reset():位容器的所有位置0

bitset &flip():位容器的所有位置反转

这题 bitset 的使用相当于是作为一个指针来使用的。

首先用bitset定义出现的数会在哪几位上出现,置为1。

定义ans的初始位为1,每一次母串对应位与该位出现的数的bitset进行与比较(表明该位上是否能出现该数)。因为一旦失败则置0,因此如果1出现在ans的第n位上则表明之前的n-1位全部匹配成功。

此题,使用bitset的复杂度为O(n*len/x)(len为母串长,x为机器码长)。

b[i][j]表示值为i的数可以出现在字串的哪些位上,遍历主串即可。

另外定义bitset<N> ans,每次讲ans左移一位,然后将最低位置1,令k等于当前输入的数,将ans = ans&b[k],如果当前ans[N-1]==1,那么主串s[i-N+1]~s[i]符合要求,输出。此题必须使用puts,gets进行输入输出,不然会超时。

//
//  main.cpp
//  160929
//
//  Created by 刘哲 on 17/5/30.
//  Copyright © 2016年 my_code. All rights reserved.
//#include <bits/stdc++.h>

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <string.h>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <list>
#include <bitset>
#include <stack>
#include <stdlib.h>
#define lowbit(x) (x&-x)
typedef long long ll;
using namespace std;
bitset<1005>b[11];
bitset<1005>ans;
char s[5000005];
int main()
{
    int n;
    while(cin>>n)
    {
        for(int i=0;i<10;i++)
            b[i].reset();
        for(int i=0;i<n;i++)
        {
            int t;
            scanf("%d",&t);
            for(int j=1;j<=t;j++)
            {
                int k;
                scanf("%d",&k);
                b[k].set(i);
            }
        }
        getchar();
        gets(s);
        ans.reset();
        int len = strlen(s);
        for(int i=0;i<len;i++)
        {
            ans<<=1;
            ans.set(0);
            ans&=b[s[i]-'0'];
            if(ans[n-1]==1)
            {
                char tmp = s[i+1];
                s[i+1] = 0;
                puts(s+i+1-n);
                s[i+1] = tmp;
            }
        }
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值