题目链接:http://www.bnuoj.com/bnuoj/problem_show.php?pid=26580
题意:给一个模式串,然后m个匹配串,要求删掉匹配串中的所有存在的模式串,使得余下的串中没有模式串。
数据很大,需要O(N)的算法。。。
首先kmp求出模式串的next数组,然后就是kmp匹配了。
但是我们要注意到是要删尽,如BBUGUG,这个样例是删没了的,因此在kmp匹配的时候,对于每个字符 i,我们需要维护两个值 l 和 r,分别表示 i 的左边的有效字符串的下标和右边有效字符串的下标。同时还要维护一个cur[i]数组,表示位置为 i 的字符的next值。然后如果匹配到一个,把这个删掉标记,重新从这个匹配串的起始点的前一个有效字符开始匹配,同时令k=next[l[i]]。直到没有匹配为止。
1 //STATUS:C++_AC_928MS_4812KB 2 #include <cmath> 3 #include <cstdio> 4 #include <cstring> 5 #include <iostream> 6 #include <algorithm> 7 using namespace std; 8 #define mem(a,b) memset(a,b,sizeof(a)) 9 typedef long long LL; 10 11 const int N=2000010; 12 13 char s[N],p[N]; 14 int vis[N]; 15 int next[N]; 16 int l[N],r[N],cur[N]; 17 int T,n,m; 18 19 void getnext(char *s,int len) 20 { 21 int j=0,k=-1; 22 next[0]=-1; 23 while(j<len){ 24 if(k==-1 || s[k]==s[j]) 25 next[++j]=++k; 26 else k=next[k]; 27 } 28 } 29 30 void getw(int lens,int lenp) 31 { 32 int i,j,k; 33 for(i=0;i<lens;i++){ 34 vis[i]=0,l[i]=i-1,r[i]=i+1; 35 } 36 for(i=k=0;i<lens;i=r[i]){ 37 while(p[k]!=s[i] && k>=0)k=next[k]; 38 cur[i]=++k; 39 if(k==lenp){ 40 int end=r[i]; 41 for(j=lenp;j--;i=l[i])vis[i]=1; 42 r[i]=end;l[end]=i; 43 k=cur[i]; 44 } 45 } 46 } 47 48 int main(){ 49 // freopen("in.txt","r",stdin); 50 int i,j,lenp,lens; 51 while(~scanf("%d%s",&n,p)) 52 { 53 getchar(); 54 lenp=strlen(p); 55 getnext(p,lenp); 56 while(n--){ 57 gets(s); 58 lens=strlen(s); 59 getw(lens,lenp); 60 for(i=j=0;i<lens;i++){ 61 if(vis[i])continue; 62 else putchar(s[i]); 63 } 64 putchar(' '); 65 } 66 } 67 return 0; 68 }