题意:
给你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;
}