Number Sequence
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 11447 Accepted Submission(s): 5217
Problem Description
Given two sequences of numbers : a[1], a[2], ...... , a[N], and b[1], b[2], ...... , b[M] (1 <= M <= 10000, 1 <= N <= 1000000).
Your task is to find a number K which make a[K] = b[1], a[K + 1] = b[2], ...... , a[K + M - 1] = b[M]. If there are more than one K exist, output the smallest one.
Input
The first line of input is a number T which indicate the number of cases. Each case contains three lines. The first line is
two numbers N and M (1 <= M <= 10000, 1 <= N <= 1000000). The second line contains N integers which indicate a[1], a[2], ...... , a[N]. The third line contains M integers which indicate b[1], b[2], ...... , b[M]. All integers are in the range of [-1000000,
1000000].
Output
For each test case, you should output one line which only contain K described above. If no such K exists, output -1 instead.
Sample Input
2 13 5 1 2 1 2 3 1 2 3 1 3 2 1 2 1 2 3 1 3 13 5 1 2 1 2 3 1 2 3 1 3 2 1 2 1 2 3 2 1
Sample Output
6 -1非常典型的KMP算法的问题。这个算法我在基础讲解结合资料大概说了说,其实很弱..(强烈推荐严蔚敏老师的《数据结构》其中有讲解)我觉得这个算法的难点就是理解失配函数已经求解失配函数的过程。有必要在说明一下,作为那篇算法的讲解的补充。先给出代码:<span style="font-family:Microsoft YaHei;font-size:14px;">void get_failure(int m)//m分别为pat字符串的长度 { int j = 0 , k = -1; failure[0] = -1; while(j < m) { if(k == -1 || pat[j] == pat[k]){ j++; k++; failure[j] = k; } else k = failure[k]; } }</span>
failure[i]即失配函数。
我们以字符串 abcba为例,其failure函数为:
i 0 1 2 3 4 5
s a b c b a
f -1 0 0 0 0 1
这个结果其实是用<strong>pat字符串和它自身进行模式匹配得出的。即pat即是源字符串也是模式串。
j是pat(在该函数中相当于源字符串)的下标。
k是pat(在这个函数中相当于模式串)的下标。初始值是-1,是给字符串abcba假定有一个字符在下标为-1的位置,可以表示成这样
下面就自己动笔算一下(abcba)的失配函数+《数据结构》的解释,大概就能慢慢懂了。
附AC代码,500MS<span style="font-family:Microsoft YaHei;font-size:14px;">#include <stdio.h> #include <string.h> #define maxn 1000005 int source[maxn]; int pat[maxn];//pattern int failure[maxn];//失配函数 void initialize(int N,int M) { for(int i = 0 ; i < N ; ++i) source[i] = 0; for(int i = 0 ; i < M ; ++i) pat[i] = 0; memset(failure,0,sizeof(failure)); } void get_failure(int n,int m) { int j = 0 , k = -1; failure[0] = -1; while(j < m) { if(k == -1 || pat[j] == pat[k]){ j++; k++; failure[j] = k; } else k = failure[k]; } } int KMP(int n,int m) { int i = 0 , j = 0; while(i < n) { //j == -1表示pat从头来过 if(source[i] == pat[j] || j == -1){ i++; j++; } else j = failure[j]; if(j == m) return i - m + 1; } return -1; } int main() { int CaseNum; int N,M; while(scanf("%d",&CaseNum) != EOF) { while(CaseNum--) { scanf("%d%d",&N,&M); initialize(N,M); for(int i = 0 ; i < N ; ++i) scanf("%d",&source[i]); for(int i = 0 ; i < M ; ++i) scanf("%d",&pat[i]); get_failure(N,M); int ans = KMP(N,M); printf("%d\n",ans); } } return 0 ; } /*——————暴力匹配—————— 注意const的用法,去掉之后编译会出现waring,看看 */ /* #include <stdio.h> #include <string.h> int BFmatch(const char *s, const char *t) { int i = 0; while(i < strlen(s)) { int j = 0; while(s[i] == t[j] && j < strlen(t)) { i++; j++; } if(j == strlen(t)) return i - strlen(t); i = i - j + 1; } return 0; } int main() { const char * s = "ababcababa"; const char * t = "ababa"; int pos = BFmatch(s,t); printf("The position is : %d\n",pos); return 0; } */</span>