BNUOJ-26580 Software Bugs KMP匹配,维护

  题目链接: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('\n');
65         }
66     }
67     return 0;
68 }

 

posted @ 2013-08-27 02:24  zhsl  阅读(289)  评论(0编辑  收藏  举报