HDU 5918 Sequence I KMP

Sequence I

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,?,bmis 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

Sample Output

Case #1: 2
Case #2: 1

题意:

  给你a,b两个序列

  和一个p ,求有多少个 q恰好满足 b1,b2,b3....bm 就是 a[q],a[q+p],a[q+2p]......a[q+(m-1)p];

题解:

  将a序列,每隔p位置分成一组,这样最多有p组,个数和是n

  将每组和b序列跑KMP计算答案

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair
typedef long long LL;
const long long INF = 1e18;
const double Pi = acos(-1.0);
const int N = 1e6+10, M = 1e6, mod = 1e9+7, inf = 2e9;

int T,n,m,p,s[N],t[N],ans = 0;
vector<int > P[N];
int nex[N];
int main()
{
    int cas = 1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&p);
        for(int i = 1; i <= n; ++i) scanf("%d",&t[i]);
        for(int i = 1; i <= m; ++i) scanf("%d",&s[i]);
        for(int i = 0; i < p; ++i) P[i].clear();
        memset(nex,0,sizeof(nex));
        ans = 0;
        int k = 0;
        for(int i=2; i<=m; i++)
        {
            while(k>0&&s[k+1]!=s[i]) k = nex[k];
            if(s[k+1]==s[i])k++;
            nex[i] = k;
        }
        if(p == 1)
        {
            k = 0;
            for(int i=1; i<=n; i++)
            {
                while(k>0&&s[k+1]!=t[i]) k = nex[k];
                if(s[k+1]==t[i]) k++;
                if(k==m) {
                    k = nex[k];
                    ans++;
                }
            }
            printf("Case #%d: ",cas++);
            printf("%d\n",ans);
        }
        else {
            for(int i = 1; i <= n; ++i)
                P[i % p].push_back(t[i]);
            for(int i = 0; i < p; ++i) {
                k = 0;
                for(int j = 0; j < P[i].size(); ++j) {
                    while(k>0&&s[k+1]!=P[i][j]) k = nex[k];
                    if(s[k+1]==P[i][j]) k++;
                    if(k==m) {
                        k = nex[k];
                        ans++;
                    }
                }
            }
            printf("Case #%d: ",cas++);
            printf("%d\n",ans);

        }
    }
}
时间: 2024-10-12 15:54:54

HDU 5918 Sequence I KMP的相关文章

HDU 5918 Sequence I (KMP)

Sequence I Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2330    Accepted Submission(s): 874 Problem Description Mr. Frog has two sequences a1,a2,?,an and b1,b2,?,bm and a number p. He wants t

hdu 5918 Sequence I

给两个数组a , b,并给一个间隔值p.问在间隔值p下b在中有多少个匹配. 比如a数组为1 2 2 4 3,b数组为1 2 3,那么在间隔值为2的情况下有一个匹配. 把a数组中可以作为开头的所有间隔数字比如2可以开头的数字是1或者2,3可以开头的数字是1.2.3取出来. 然后做p次kmp即可. //#define test #include<bits/stdc++.h> using namespace std; const int Nmax=2e6+7; int f[Nmax]; int fl

HDU 1686 Oulipo(KMP)

Problem Description The French author Georges Perec (1936–1982) once wrote a book, La disparition, without the letter 'e'. He was a member of the Oulipo group. A quote from the book: Tout avait Pair normal, mais tout s'affirmait faux. Tout avait Fair

HDU 3397 Sequence operation(线段树)

HDU 3397 Sequence operation 题目链接 题意:给定一个01序列,有5种操作 0 a b [a.b]区间置为0 1 a b [a,b]区间置为1 2 a b [a,b]区间0变成1,1变成0 3 a b 查询[a,b]区间1的个数 4 a b 查询[a,b]区间连续1最长的长度 思路:线段树线段合并.须要两个延迟标记一个置为01,一个翻转,然后因为4操作,须要记录左边最长0.1.右边最长0.1,区间最长0.1,然后区间合并去搞就可以 代码: #include <cstdi

hdu 3746 Cyclic Nacklace (KMP求最小循环节)

//len-next[len]为最小循环节的长度 # include <stdio.h> # include <algorithm> # include <string.h> using namespace std; int len; char a[100010]; int next[100010]; void Getnext() { int i=0,j=-1; next[0]=-1; while(i<=len) { if(j==-1||a[i]==a[j]) i

hdu 5667 Sequence 矩阵快速幂

题目链接:hdu 5667 Sequence 思路:因为fn均为a的幂,所以: 这样我们就可以利用快速幂来计算了 注意: 矩阵要定义为long long,不仅仅因为会爆,还会无限超时 要对a%p==0特判,以为可能出现指数%(p-1)==0的情况,那么在快速幂的时候返回的结果就是1而不是0了 /************************************************************** Problem:hdu 5667 User: youmi Language:

HDU 3998 Sequence(经典问题,最长上升子序列)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3998 解题报告:求一个数列的最长上升子序列,并求像这样长的不相交的子序列最多有多少个. 我用的是最简单的方法,就是每次求最长上升子序列,然后每次将求得的子序列从数列里面删掉,然后再对剩下的数列求最长上升子序列,如果求得的子序列的长度比第一次求得的长度小的话,就退出.不过我这题卡了很久,原因就是因为用这种方法求的过程中,用到了很多变量,但是没有注意每一步求最长上升子序列的时候都要进行初始化,哎. Vi

hdu 5510 Bazinga(字符串kmp)

Bazinga Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2287    Accepted Submission(s): 713 Problem Description Ladies and gentlemen, please sit up straight.Don't tilt your head. I'm serious.For

hdu 5147 Sequence II(树状数组)

题目链接:hdu 5147 Sequence II 预处理每个位置作为b和c可以组成的对数,然后枚举b的位置计算. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 50005; int N, arr[maxn], fenw[maxn], lef[maxn], rig[maxn]; #d