【Foreign】字符串匹配 [KMP]

字符串匹配

Time Limit: 10 Sec  Memory Limit: 256 MB

Description

  

Input

  

Output

  

Sample Input

  3 3
  6 3
  1 2 1 2 3 2
  3 1 3
  6 3
  1 2 1 2 1 2
  3 1 3
  6 3
  1 1 2 1 2 1
  3 1 3

Sample Output

  3
  1 2 4
  4
  1 2 3 4
  3
  2 3 4

HINT

  

Solution

  发现题目中颜色的具体权值是对答案无关的,然后就是只要相对位置一样即可。

  那么显然是一个KMP的模型,变相更改,条件改为:两个字符上一次出现的相对位置相同(也就是位置差值相等)

  那么我们只要求出差值来KMP即可,再考虑一下串长对于答案的影响,差值>串长显然是不会影响答案的,但是直接匹配的话可能将这种情况默认为不可行,所以我们在匹配的时候判断一下串长,若dist>=当前匹配串长则同设为0即可,更新fail的时候也要这么做。这样做KMP即可求出答案。

Code

 1 #include<iostream>
 2 #include<string>
 3 #include<algorithm>
 4 #include<cstdio>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<ctime>
 8 #include<cmath>
 9 using namespace std;  
10 
11 const int ONE=10001;
12 
13 int T,C;
14 int n,m;
15 int a[ONE],b[ONE];
16 int da[ONE],db[ONE],la[ONE],lb[ONE];
17 int fail[ONE],j;
18 int Ans[ONE],ans_num;
19  
20 int get()
21 {    
22         int res=1,Q=1;char c;
23         while( (c=getchar())<48 || c>57 )
24         if(c=='-')Q=-1;
25         res=c-48;
26         while( (c=getchar())>=48 && c<=57 )
27         res=res*10+c-48;
28         return res*Q;
29 }
30 
31 int Da(int i,int len) {if(da[i]>=len) return 0;return da[i];}
32 int Db(int i,int len) {if(db[i]>=len) return 0;return db[i];}
33 
34 int main()
35 {
36         T=get();    C=get();
37         while(T--)
38         {
39             n=get();    m=get();
40             memset(la,0,sizeof(la));    memset(lb,0,sizeof(lb));
41             for(int i=1;i<=n;i++) a[i]=get();
42             for(int i=1;i<=m;i++) b[i]=get();
43             
44             for(int i=1;i<=n;i++) da[i]=i-la[a[i]], la[a[i]]=i;
45             for(int i=1;i<=m;i++) db[i]=i-lb[b[i]], lb[b[i]]=i;
46             
47             j=0;
48             for(int i=2;i<=m;i++)
49             {
50                 j=fail[i-1];
51                 while(j && Db(j+1,j+1)!=Db(i,j+1)) j=fail[j];
52                 if(Db(j+1,j+1) == Db(i,j+1)) j++; else j=0;
53                 fail[i] = j;
54             }
55             
56             j=0;    ans_num=0;
57             for(int i=1;i<=n;i++)
58             {
59                 while(j && Db(j+1,j+1)!=Da(i,j+1)) j=fail[j];
60                 if(Db(j+1,j+1) == Da(i,j+1)) j++; else j=0;
61                 if(j==m) Ans[++ans_num] = i-m+1, j=fail[j];
62                 
63             }
64             
65             printf("%d\n",ans_num);
66             for(int i=1;i<=ans_num;i++)
67                 printf("%d ",Ans[i]);
68             printf("\n");
69         }
70 }
View Code

 

posted @ 2017-03-02 20:37  BearChild  阅读(163)  评论(0编辑  收藏  举报