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 }

 

你可能感兴趣的:(software)