CodeForces

来源:互联网 发布:人工智能贴吧 编辑:程序博客网 时间:2024/06/07 05:37

题目链接:http://codeforces.com/problemset/problem/471/D

题目大意:有两个数组A,B,B数组中的数可以同时减或加同一个数,去和A数组中的连续子串匹配

解题思路:匹配问题就想到了KMP,有一点麻烦的就是匹配的高度可以随意,然后我们去观察对于那些匹配成功的串的特点,就是他们的相对高度只要和匹配串的相对高度一致,那么他们肯定是匹配的,所以把A,B预处理成相邻的高度差,发现第一个匹配的数的高度可以随意,只要匹配第二个一直到最后一个他们的相对高度是否一致就可以了

AC代码:

#include<cstdio>#include<cstring>using namespace std;const int Maxn = 2 * 100000 + 5;int sum;int A[Maxn], B[Maxn],next[Maxn];void getNext(int p[],int next[],int len){    int i = 0, j = -1;    next[0] = -1;    while (i < len)    {        if (j == -1 || p[i] == p[j])        {            i++, j++;            next[i] = j;        }        else j = next[j];    }}int toKmp(int s[],int p[],int next[],int s_len,int p_len){    getNext(p, next,p_len);    int i = 0, j = 0;    while (i < s_len&&j < p_len)    {        if (j == -1 || s[i] == p[j])            i++, j++;        else            j = next[j];        if (j == p_len)//匹配成功,把当作匹配不成功,继续匹配        {            sum++;            j = next[j];        }    }    if(j==p_len) return i - j;    return -1;}int main(){    sum = 0;    int n, m;scanf("%d%d", &n, &m);    for (int i = 0;i < n;++i)        scanf("%d", A + i);    for (int j = 0;j < m;++j)        scanf("%d", B + j);    //由于匹配忽略第一位,所以这里特判一下只有一位的数组    if (m == 1)    {        printf("%d\n", n);        return 0;    }    if (n == 1 && m != 1)    {        printf("0\n");        return 0;    }    for (int i = n - 1;i >= 1;--i)        A[i] -= A[i - 1];    for (int i = m - 1;i >= 1;--i)        B[i] -= B[i - 1];    toKmp(A + 1, B + 1, next, n - 1, m - 1);//匹配到的第一个的高度可以随意,所以直接不匹配第一个    printf("%d\n", sum);    return 0;}