Regular Number--hdu5972

Regular Number

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1644    Accepted Submission(s): 445


Problem Description
Using regular expression to define a numeric string is a very common thing. Generally, use the shape as follows:
(0|9|7) (5|6) (2) (4|5)
Above regular expression matches 4 digits:The first is one of 0,9 and 7. The second is one of 5 and 6. The third is 2. And the fourth is one of 4 and 5. The above regular expression can be successfully matched to 0525, but it cannot be matched to 9634.
Now,giving you a regular expression like the above formula,and a long string of numbers,please find out all the substrings of this long string that can be matched to the regular expression.
 

Input
It contains a set of test data.The first line is a positive integer N (1 ≤ N ≤ 1000),on behalf of the regular representation of the N bit string.In the next N lines,the first integer of the i-th line is  ai(1ai10) ,representing that the i-th position of regular expression has  ai  numbers to be selected.Next there are  ai  numeric characters. In the last line,there is a numeric string.The length of the string is not more than 5 * 10^6.
 

Output
Output all substrings that can be matched by the regular expression. Each substring occupies one line
 

Sample Input
  
  
4 3 0 9 7 2 5 7 2 2 5 2 4 5 09755420524
 

Sample Output
  
  
9755 7554 0524
 

Source

学会使用bitset。
一共就九个数字。所以可以将每个数字对应的数组的出现过的位置置为1,没出现过置为0.
比如b[5]对应的就是0111
对于bitset<n>ans,每次左移一位,并将最低位置一,然后让ans和字符串这个位置的字符对应的数组进行与运算。
如果ans[k]=1表示从这个位置开始往前的长度为k+1的串可以和子串的前缀进行匹配。
把低位置一,这样就保证了只有匹配,这个1才能往下传递,所以一直传递到第n-1位,这样代表都匹配了。
当ans[n-1]的时候,说明从i-n+1位置开始的母串可以和子串匹配,这个时候输出
然后就是数据很大得使用gets puts 才不超时。
#include <iostream>
#include<bitset>
#include<cstdio>
using namespace std;
const int maxn=5*1e6+5;
bitset<1005>b[11];
bitset<1005>ans;
char s[maxn];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        for(int i=0;i<10;i++)
        b[i].reset();                   //将b[i]中所有二进制位置0
        for(int i=0;i<n;i++)
        {
            int num;
            scanf("%d",&num);
            for(int j=0;j<num;j++)
            {
                int tmp;
                scanf("%d",&tmp);
                b[tmp].set(i);                     //把b[tmp]的i位二进制置为1
            }
        }
       // getchar();
        scanf(" %s",s);
        ans.reset();
        for(int i=0;s[i]!='\0';i++)
        {
            ans=ans<<1;
            ans.set(0);
            ans=ans&b[s[i]-'0'];
            if(ans[n-1]==1)                            //注意这种输出方式
            {
                char c=s[i+1];
                s[i+1]='\0';
                puts(s+i-n+1);
                s[i+1]=c;
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值