Sequence I
Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 216 Accepted Submission(s): 93
Problem Description
Mr. Frog has two sequences a1,a2,⋯,an and b1,b2,⋯,bm and a number p. He wants to know the number of positions q such that sequence b1,b2,⋯,bm is exactly the sequence aq,aq+p,aq+2p,⋯,aq+(m−1)p where q+(m−1)p≤n and q≥1.
Input
The first line contains only one integer T≤100, which indicates the number of test cases.
Each test case contains three lines.
The first line contains three space-separated integers 1≤n≤106,1≤m≤106 and 1≤p≤106.
The second line contains n integers a1,a2,⋯,an(1≤ai≤109).
the third line contains m integers b1,b2,⋯,bm(1≤bi≤109).
Output
For each test case, output one line “Case #x: y”, where x is the case number (starting from 1) and y is the number of valid q’s.
Sample Input
2
6 3 1
1 2 3 1 2 3
1 2 3
6 3 2
1 3 2 2 3 1
1 2 3
6 3 1
1 2 3 1 2 3
1 2 3
6 3 2
1 3 2 2 3 1
1 2 3
Sample Output
Case #1: 2
Case #2: 1
Case #2: 1
Source
题意:给定数组 a1...an ,b1...bm, 以及间隔 d,问 a 中使得存在 aq ,aq+d , aq+2d...aq+(m-1)d 和 b数组相等的 q 有多少个?
题解:标准解法是 KMP,我这双重循环强行水了过去..
#include <bits/stdc++.h>
using namespace std;
const int N = ;
int a[N],b[N];
int main()
{
int tcase,t=;
scanf("%d",&tcase);
while(tcase--){
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=;i<=m;i++){
scanf("%d",&b[i]);
}
if(m>n) {
printf("Case #%d: %d\n",t++,);
continue;
}
int ans = ;
for(int i=;i<=n;i++){
if(a[i]!=b[]) continue;
int idx = ;
for(int j=i;j<=n;j+=k){
if(a[j]==b[idx]){
idx++;
}
else break;
if(idx==m+){
ans++;break;
}
}
}
printf("Case #%d: %d\n",t++,ans);
}
return ;
}
KMP解法
#include <iostream>
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
using namespace std; const int N = ;
int Next[N];
int A[N],S[N], T[N];
int slen, tlen; void getNext()
{
int j, k;
j = ; k = -; Next[] = -;
while(j < tlen)
if(k == - || T[j] == T[k])
Next[++j] = ++k;
else
k = Next[k]; }
/*
返回模式串在主串S中出现的次数
*/
int KMP_Count()
{
int ans = ;
int i, j = ;
if(slen == && tlen == )
{
if(S[] == T[])
return ;
else
return ;
}
for(i = ; i < slen; i++)
{
while(j > && S[i] != T[j])
j = Next[j];
if(S[i] == T[j])
j++;
if(j == tlen)
{
ans++;
j = Next[j];
}
}
return ans;
}
int main()
{ int tcase,t=;
scanf("%d",&tcase);
while(tcase--)
{
int n,k;
scanf("%d%d%d",&n,&tlen,&k); memset(T,,sizeof(T));
for(int i=;i<n;i++) scanf("%d",&A[i]);
for(int i=;i<tlen;i++) scanf("%d",&T[i]);
int ans = ;
getNext();
for(int i=;i<k;i++){ ///枚举起点
slen = ;
for(int j = i;i+(tlen-)*k<n&&j<n;j+=k){
S[slen++] = A[j];
}
if(slen<tlen) continue;
/*for(int j=0;j<slen;j++){
printf("%d ",S[j]);
}*/
ans+=KMP_Count();
}
printf("Case #%d: %d\n",t++,ans);
}
return ;
}