链接
题意
CCPC的H题。
给出序列a、b和一个周期p,找出b出现在a中的位置:a[q + kp](k from 0 to len(b) - 1),q的个数。
题解
很简单的匹配问题,容易将a分成周期为p的p组,每组跟b进行匹配,匹配次数就是答案。
代码
#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long lint;
#define next naxt
#define maxn (1000010)
int a[maxn], b[maxn];
vector<int> v[maxn];
int next[maxn];
void pre_kmp(const int a[], int n)
{
memset(next, 0, sizeof(int)*(n+1));
for(int i = 0, j; i < n; i++)
{
j = i;
while(j > 0)
{
j = next[j];
if(a[i] == a[j])
{
next[i + 1] = j + 1;
break;
}
}
}
}
int kmp(vector<int>& b, int m, const int a[], int n)
{
int ret = 0;
for(int i = 0, j = 0; i < m; i++)
{
if(b[i] == a[j])
{
j++;
}
else
{
while(j > 0)
{
j = next[j];
if(b[i] == a[j])
{
j++;
break;
}
}
}
if(j == n) ret++;
}
return ret;
}
int main()
{
int T, kase = 0;
cin >> T;
while(T--)
{
int n, m, p;
cin >> n >> m >> p;
for(int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
v[i % p].push_back(a[i]);
}
for(int i = 0; i < m; i++)
scanf("%d", &b[i]);
b[m] = 0;
pre_kmp(b, m);
lint ans = 0;
for(int i = 0; i < p; i++)
{
if(v[i].size() > 0)
ans += kmp(v[i], v[i].size(), b, m);
v[i].clear();
}
printf("Case #%d: ", ++kase);
cout << ans << endl;
}
return 0;
}