地址:
题目:
带可选字符的多字符串匹配
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 763 Accepted Submission(s): 171
Problem Description
有一个文本串,它的长度为m(1≤m≤2000000),现在想找出其中所有的符合特定模式的子串位置。
符合特定模式是指,该子串的长度为n(1≤n≤500),并且第i个字符需要在给定的字符集合Si中。
因此,描述这一特定模式,共需要S1,S2,...,Sn这n个字符集合。每个集合的大小都在1∼62之间,其中的字符只为数字或大小写字母。
Input
第一行为一个字符串,表示待匹配的文本串。注意文本串中可能含有数字和大小写字母之外的字符。
第二行为一个整数n。
以下n行,分别描述n个字符集合。每行开始是一个1∼62之间的整数,随后有一个空格,接下来有一个字符串表示对应字符集合的内容。整数表示字符集合的大小,因此它也就是字符串的长度。输入保证字符串中的字符只为数字或大小写字母且没有重复。<b>(注:本题有多组测试数据)</b>
Output
每当从某个位置开头的,长度为n的子串符合输入的模式,就输出一行,其中包含一个整数,为它在文本串的起始位置。位置编号从1开始。
如果文本串没有任何位置符合输入模式,则最后输出一个字符串"NULL",占一行。
Sample Input
aaaabacabcabd
3
3 abc
2 bc
3 abc
Sample Output
4
6
8
9
Source
思路:
shiftand算法,不会的先百度吧。
因为模式串比较长,所以bitset状压一下。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define MP make_pair 6 #define PB push_back 7 typedef long long LL; 8 typedef pair<int,int> PII; 9 const double eps=1e-8; 10 const double pi=acos(-1.0); 11 const int K=1e6+7; 12 const int mod=1e9+7; 13 14 int getidx(char c) 15 { 16 if(‘0‘<=c&&c<=‘9‘) return c-‘0‘; 17 if(‘a‘<=c&&c<=‘z‘) return c-‘a‘+11; 18 if(‘A‘<=c&&c<=‘Z‘) return c-‘A‘+37; 19 return 63; 20 } 21 22 char sa[2000007],sb[300]; 23 bitset<500>bt[65],d; 24 int n; 25 int main(void) 26 { 27 //freopen("in.acm","r",stdin); 28 while(gets(sa)) 29 { 30 memset(bt,0,sizeof bt); 31 scanf("%d",&n); 32 for(int i=0,len;i<n;i++) 33 { 34 scanf("%d%s",&len,sb); 35 for(int j=0;j<len;j++) bt[getidx(sb[j])][i]=1; 36 } 37 int len=strlen(sa),ff=0; 38 d.reset(); 39 for(int i=0;i<len;i++) 40 { 41 d <<=1; 42 d[0]=1; 43 d &= bt[getidx(sa[i])]; 44 if(d[n-1]) printf("%d\n",i-n+2),ff=1; 45 } 46 getchar(); 47 if(!ff) printf("NULL\n"); 48 } 49 return 0; 50 }
时间: 2024-10-11 21:51:34