kmp变形,带通配符的kmp——华科校赛E 好题

https://blog.csdn.net/a302549450/article/details/80948741?tdsourcetag=s_pctim_aiomsg

上面是题解的链接。。,

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define PI acos(-1)
#define INF 0x3f3f3f3f
#define NUM 101000
#define debug false
#define ll long long
#define lowbit(x) ((-(x))&(x))
#define ffor(i,d,u) for(int i=(d);i<=(u);++i)
#define _ffor(i,u,d) for(int i=(u);i>=(d);--i)
#define mst(array,Num) memset(array,Num,sizeof(array))
const int p = 1e9+7;
int n,k,m,_next[NUM],a[NUM<<1],b[NUM],ori[NUM<<1],par[NUM],pos[12];
int ans=0;
template <typename T>
void read(T& x)
{
    x=0;
    char c;
    while((c=getchar())<‘0‘||c>‘9‘);
    do((x*=10)+=((int)(c-‘0‘)));while((c=getchar())>=‘0‘&&c<=‘9‘);
}
template <typename T>
void write(T x)
{
    int len=0;char c[21];
    if(x<0)putchar(‘-‘);
    x=abs(x);
    do{++len;c[len]=(char)((x%10)+‘0‘);}while(x/=10);
    _ffor(i,len,1)putchar(c[i]);
}
void build()
{
    mst(pos,-1);
    par[1]=-1;
    pos[b[1]]=1;
    ffor(i,2,m)
    {
        if(pos[b[i]]!=-1)
            par[i]=i-pos[b[i]];
        else
            par[i]=-1;
        pos[b[i]]=i;
    }
    mst(pos,-1);
    ori[1]=-1;
    pos[a[1]]=1;
    ffor(i,2,n)
    {
        if(pos[a[i]]!=-1&&i-pos[a[i]]<m)
            ori[i]=i-pos[a[i]];
        else
            ori[i]=-1;
        pos[a[i]]=i;
    }
}
int getnext(int x)
{
    int i;
    i=_next[x];
    while(i!=-1 && par[i+1]!=par[x+1] && par[i+1]!=-1 )i=_next[i];
    return i+1;
}
bool pd(int x,int y)
{ //母串的x和模式串的y相等 或者 模式串的y无前驱且(y前的长度比x前驱小)
    return (ori[x]==par[y] || (par[y]==-1 && ((y-ori[x])<1)));
}
void kmp()
{
    _next[0]=-1;_next[1]=0;
    ffor(i,2,m)
        _next[i]=getnext(i-1);
    int i=0,j=0;
    while(j<n)
    {
        while(i<m&&j<n&&pd(j+1,i+1)){++i;++j;}
        if(i==m)++ans;
        if(j==n)break;
        while(i==m||(i!=-1&&!pd(j+1,i+1)))i=_next[i];
        if(i==-1)
        {
            ++i;
            ++j;
        }
    }
}
void AC()
{
    read(n),read(k);
    ffor(i,1,n)
        read(a[i]);
    read(m);
    ffor(i,1,m)
        read(b[i]);
    build();
    kmp();
    write(ans);
}
int main()
{
    AC();
    return 0;
}

原文地址:https://www.cnblogs.com/zsben991126/p/10917316.html

时间: 2024-10-29 12:30:54

kmp变形,带通配符的kmp——华科校赛E 好题的相关文章

2016 华科校赛 B. And

// 2016 华科校赛 B. And http://acm.hust.edu.cn/problem/show/1672 题目描述 给出 a[1], ..., a[n].查询 t[1], ... t[m],问有多少 a[] 的子序列的按位与是 t[]. 输入 多组测试,EOF 结束. n a[] m t[] 1 ≤ n ≤ 1e6 1 ≤ m ≤ (1 << 20) 1 ≤ a[i] ≤ (1 << 20) 1 ≤ t[i] ≤ (1 << 20) 输出 输出一行,每组

ZJU校赛 一道计数题

题意是这样的 给定一个n*m的整数矩阵 n和m均小于1000 对这个矩阵删去任意行和列后剩余一个矩阵为M{x1,x2,,,,xm;y1,y2,,,,,yn}表示删除任意的M行N列 对于这个剩下的矩阵,我们考虑其中是否存在特殊的元素,保证这些元素是所在行最大,所在列最小的元素 且非之一. 求对于所有删法,上述元素个数之和 对10^9+7取余. 显然所有删法 有2^(n+m)种 暴力是搞不定的. 于是反过来看,矩阵的元素最多有10^6个 是不是可以考虑每一个元素对最终答案的贡献? 所谓贡献,就是它在

Fire Air(华科校赛 网络赛)

题目 原题链接:https://www.nowcoder.com/acm/contest/106/L 在100000 * 10000的空地上,有n个时间点,每个时间点会在(xi,yi)上种一棵树. 定义绿色:被树包围的空地的个数. 问每个时间点之后绿色为多少.如图: 思路 逆向求解,从(0,0)位置将圈外的全标记(给空地加一圈),在分别考虑当前的树,是在圈内还是圈的外围. 由于vis是全局数组,之后的bfs都非常快,每个点只遍历过一次. 代码实现 1 #include<stdio.h> 2 #

校赛部分水题

1236: xq and Crystal Mine Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 313  Solved: 76 [Submit][Status][Web Board] Description xq once got a crystal from the Crystal Mine. A crystal of size n (n is odd; n>1) is an n?*?n matrix with a diamond inscr

算法笔记_216:第六届蓝桥杯软件类校赛部分真题(Java语言C组)

目录 1 题目一 2 题目二 3 题目三 4 题目四 5 题目五 前言:以下代码仅供参考,若有错误欢迎指正哦~ 1 题目一 二项式的系数规律,我国数学家很早就发现了. 如[图1.png],我国南宋数学家杨辉1261年所著的<详解九章算法>一书里就出现了. 其排列规律: 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 1 6 15 20 15 6 1 1 7 21 35 35 21 7 1 如下的程序,用来建立N行的杨辉三角形.请填写划线部分缺少的代码.

算法笔记_215:第六届蓝桥杯软件类校赛部分真题(Java语言B组)

目录 1 题目一 2 题目二 3 题目三 前言:以下代码仅供参考,若有错误欢迎指正哦~ 1 题目一 java中提供了对正则表达式的支持. 有的时候,恰当地使用正则,可以让我们的工作事半功倍! 如下代码用来检验一个四则运算式中数据项的数目,请填写划线部分缺少的代码. 注意:只填写缺少代码,不要写任何多余内容,例如,已有的双引号. public class A { public static int f(String s) { return s.split("________________&quo

2018bnu校赛总结

····我好菜,完全没有准确率只写了签到,完全被吊打QAQ 大概就是自己懒惰的后果吧qwq A 塞特斯玛斯塔 签到···我因为是多组样例wa了一发···· #include <bits/stdc++.h> using namespace std; char s[100010]; int main() { int t,n;scanf("%d",&t); while(t--){ scanf("%d",&n); int cnt=0; for(i

openjudge6252 带通配符的字符串匹配

描述 通配符是一类键盘字符,当我们不知道真正字符或者不想键入完整名字时,常常使用通配符代替一个或多个真正字符.通配符有问号(?)和星号(*)等,其中,“?”可以代替一个字符,而“*”可以代替零个或多个字符. 你的任务是,给出一个带有通配符的字符串和一个不带通配符的字符串,判断他们是否能够匹配. 例如,1?456 可以匹配 12456.13456.1a456,但是却不能够匹配23456.1aa456: 2*77?8可以匹配 24457798.237708.27798. 输入输入有两行,每行为一个不

KMP算法的定义及KMP练手题 HDU 1711 Number Sequence (我的模板代码)

题意:就是要你来找出b数组在a数组中最先匹配的位置,如果没有则输出-1 思路:直接KMP算法(算法具体思想这位牛写的不错http://blog.csdn.net/v_july_v/article/details/7041827) AC代码: #include<cstdio> #include<cstring> #include<stdlib.h> #include<iostream> using namespace std; #define maxn 100