代码:
#include <iostream> #include <cstring> using namespace std; const int N = 1000100; int n, m; // n 主串长度, m模式串长度 char a[N], b[N]; // a 主串, b 模式串, 下标从零开始 int nextt[N]; void get_nextt() { int i = 0, j; j = nextt[0] = -1; while(i < m) { if(-1 == j || b[i] == b[j] ) nextt[++i] = ++j; else j = nextt[j]; } } void get_nextval() { int i = 0, j; j = nextt[0] = -1; while(i < m) { if(-1 == j || b[i] == b[j]) { ++i, ++j; nextt[i] = (b[i] != b[j]) ? j : nextt[j]; } else { j = nextt[j]; } } } int kmp_index(int pos) { // 求模式串在主串 pos位置 字符之后的位置 int i = pos, j = 0; while(i < n && j < m) { if(-1 == j || a[i] == b[j]) { ++i, ++j; } else { j = nextt[j]; } } if(j >= m) return i-m; else return -1; } int kmp_count(int pos) { // 求模式串在主串中出现了几次 int i = pos, j = 0; int ans = 0; while(i < n) { if(-1 == j || a[i] == b[j]) { ++i, ++j; if(j >= m) { ++ ans; j = nextt[j]; } } else j = nextt[j]; } return ans; } int main() { cin >> a >> b; get_nextt(); get_nextval(); int Index = kmp_index( 0 ); int Count = kmp_count( 0 ); return 0; }
用两个问题验证一下:
Number Sequence
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 35581 Accepted Submission(s): 14734
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
代码:
#include <iostream> #include <cstring> #include <cstdio> using namespace std; const int N = 1000100; int n, m; // n 主串长度, m模式串长度 int a[N], b[N]; // a 主串, b 模式串, 下标从零开始 int nextt[N]; void get_nextt() { int i = 0, j; j = nextt[0] = -1; while(i < m) { if(-1 == j || b[i] == b[j] ) nextt[++i] = ++j; else j = nextt[j]; } } void get_nextval() { int i = 0, j; j = nextt[0] = -1; while(i < m) { if(-1 == j || b[i] == b[j]) { ++i, ++j; nextt[i] = (b[i] != b[j]) ? j : nextt[j]; } else { j = nextt[j]; } } } int kmp_index(int pos) { // 求模式串在主串 pos位置 字符之后的位置 int i = pos, j = 0; while(i < n && j < m) { if(-1 == j || a[i] == b[j]) { ++i, ++j; } else { j = nextt[j]; } } if(j >= m) return i-m; else return -1; } int main() { int T; cin >> T; while(T--) { cin >> n >> m; for(int i=0; i<n; i++) { scanf("%d",&a[i]); } for(int i=0; i<m; i++) { scanf("%d",&b[i]); } get_nextval(); int temp = kmp_index(0); if(temp != -1) ++ temp; cout << temp << endl; } return 0; }
2264: sequence
时间限制: 1 Sec 内存限制: 128 MB提交: 578 解决: 104
[ 提交][ 状态][ 讨论版][命题人: admin]
题目描述
给定一个含n个数的序列A和一个含m (m<=n) 个数的序列B。
询问在A中有多少段连续的长为m的子序列Ak,Ak+1,…,Ak+m-1使得对于任意1<=i, j<=m满足Ak+i-1-Bi=Ak+j-1-Bj
输入
第一行两个整数n,m (1 <= m <= n <= 106)
接下来一行n个整数,描述序列A (Ai <= 109)
接下来一行m个整数,描述序列B (Bi <= 109)
输出
输出一个数表示答案
样例输入
7 4
6 6 8 5 5 7 4
7 7 9 6
样例输出
2
#include <iostream> #include <cstring> #include <cstdio> using namespace std; const int N = 1000100; int n, m; int a[N], b[N]; int nextt[N]; void get_nextt() { int i = 0, j; j = nextt[0] = -1; while(i < m) { if(-1 == j || b[i] == b[j] ) nextt[++i] = ++j; else j = nextt[j]; } } int kmp_count(int pos) { int i = pos, j = 0; int ans = 0; while(i < n) { if(-1 == j || a[i] == b[j]) { ++i, ++j; if(j >= m) { ++ ans; j = nextt[j]; } } else j = nextt[j]; } return ans; } int main() { cin >> n >> m; for(int i=0; i<n; i++) scanf("%d",&a[i]); for(int i=0; i<m; i++) scanf("%d",&b[i]); n--, m--; for(int i=0; i<n; i++) a[i] = a[i+1] - a[i]; for(int i=0; i<m; i++) b[i] = b[i+1] - b[i]; /* for(int i=0; i<m; i++) { cout << nextt[i] << " "; } cout << endl;*/ get_nextt(); int ans = kmp_count(0); cout << ans << endl; return 0; }