第六集,想不到你这个浓眉大眼的都叛变革命了

题意:

给你两个只包含01的字符串S和T,问你在允许一次错误的情况下,T是否能成为S的子串

思路:

这个问题的解法挺多,我是用fft匹配的,也比较简单,针对0和1匹配两次,第一次针对0就是把S串和T串中等于0的位置都标记成1,然后reverse一个串后进行fft,如果这两个位置都是0,就会出现1*1=1的情况,代表有一个位置匹配上了,0这样做一次,1这样做一次,他们的和就是匹配成功的次数,所以允许一次错误就是判断和是否大于len-1。

还有一个做法是指数哈希,判断两个串的哈希值的差是否是2^n,如果是的话check一下,就做出来了,2^n可以塞到hash或者map里。

还有exkmp等其他做法你们自行了解一下

代码实现

给出fft的做法(我只写了fft)

#include <iostream>

#include <string>

#include <cstring>

#include <algorithm>

using namespace std;

typedef long long ll;

const int  N = ;

ll a[N],b[N];

const ll PMOD=(<<)+;

const ll PR=;

static ll qp[];

ll res[N];

struct NTT__container

{

    NTT__container()

    {

        int  t,i;

        for( i=; i<; i++)///注意循环上界与2n次幂上界相同

        {

            t=<<i;

            qp[i]=quick_pow(PR,(PMOD-)/t);

        }

    }

    ll quick_pow(ll x,ll n)

    {

        ll ans=;

        while(n)

        {

            if(n&)

                ans=ans*x%PMOD;

            x=x*x%PMOD;

            n>>=;

        }

        return ans;

    }

    int get_len(int n)///计算刚好比n大的2的N次幂

    {

        int i,len;

        for(i=(<<); i; i>>=)

        {

            if(n&i)

            {

                len=(i<<);

                break;

            }

        }

        return len;

    }

    inline void NTT(ll F[],int len,int type)

    {

        int id=,h,j,k,t,i;

        ll E,u,v;

        for(i=,t=; i<len; i++)

        {

            if(i>t)   swap(F[i],F[t]);

            for(j=(len>>); (t^=j)<j; j>>=);

        }

        for( h=; h<=len; h<<=)

        {

            id++;

            for( j=; j<len; j+=h)

            {

                E=;

                for(int k=j; k<j+h/; k++)

                {

                    u=F[k];

                    v=(E*F[k+h/])%PMOD;

                    F[k]=(u+v)%PMOD;

                    F[k+h/]=((u-v)%PMOD+PMOD)%PMOD;

                    E=(E*qp[id])%PMOD;

                }

            }

        }

        if(type==-)

        {

            int i;

            ll inv;

            for(i=; i<len/; i++)

                swap(F[i],F[len-i]);

            inv=quick_pow(len,PMOD-);

            for( i=; i<len; i++)

                F[i]=(F[i]%PMOD*inv)%PMOD;

        }

    }

    inline void inv(ll *a,int len)///答案存在res中

    {

        if(len==)

        {

            res[]=quick_pow(a[],PMOD-);

            return ;

        }

        inv(a,len>>);///递归

        static ll temp[N];

        memcpy(temp,a,sizeof(ll)*(len>>));

        NTT(temp,len,);

        NTT(res,len,);

        int i;

        for(i=; i<len; i++)

            res[i]=res[i]*(-temp[i]*res[i]%PMOD+PMOD)%PMOD;

        NTT(res,len,-);

        memset(res+(len>>),,sizeof(ll)*(len>>));

    }

    void mul(ll x[],ll y[],int len)///答案存在x中

    {

        int i;

        NTT(x,len,);///先映射到频域上

        NTT(y,len,);///先映射到频域上

        for(i=; i<len; i++)

            x[i]=(x[i]*y[i])%PMOD;///在频域上点积

        NTT(x,len,-);///再逆变换回时域

    }

} cal;

ll x[N],y[N],z[N];

int main()

{

    ios::sync_with_stdio(false);

    cin.tie();

    int N;

    cin>>N;

    while(N--){

        string s1,s2;

        cin>>s1>>s2;

        if(s2.length()>s1.length()){

            puts("NO");

            continue;

        }

        int len=cal.get_len(s1.length());

        //做1匹配

        memset(x,,len*sizeof(ll));

        memset(y,,len*sizeof(ll));

        memset(z,,len*sizeof(ll));

        for(int i=;i<s1.length();i++){

            x[i]=s1[i]-'';

        }

        for(int i=;i<s2.length();i++){

            y[i]=s2[i]-'';

        }

        reverse(y,y+s2.length());

        cal.mul(x,y,len);

        //for(int i=0;i<len;i++)

        for(int i=s2.length()-;i<s1.length();i++)

            z[i]+=x[i];

        //做0匹配

        memset(x,,len*sizeof(ll));

        memset(y,,len*sizeof(ll));

        for(int i=;i<s1.length();i++){

            x[i]=-(s1[i]-'');

        }

        for(int i=;i<s2.length();i++){

            y[i]=-(s2[i]-'');

        }

        reverse(y,y+s2.length());

        cal.mul(x,y,len);

        //for(int i=0;i<len;i++)

        for(int i=s2.length()-;i<s1.length();i++)

            z[i]+=x[i];

        bool flag=;

        for(int i=s2.length()-;i<s1.length();i++){

            if(z[i]>=s2.length()-){

                flag=;

                break;

            }

        }

        if(flag){

            puts("YES");

        }

        else {

            puts("NO");

        }

    }

}

福建工程学院第十四届ACM校赛J题题解的更多相关文章

  1. 福建工程学院第十四届ACM校赛M题题解 fwt进阶,手推三进制fwt

    第九集,结束亦是开始 题意: 大致意思就是给你n个3进制的数字,让你计算有多少对数字的哈夫曼距离等于i(0<=i<=2^m) 思路: 这个是一个防ak题,做法是要手推公式的fwt 大概就这 ...

  2. 福建工程学院第十四届ACM校赛G题题解

    外传:编剧说了不玩游戏不行 题意: 有n个石堆,我每次只能从某一堆中取偶数个石子,你取奇数个,我先手,先不能操作的人输.问最后谁能赢. 思路: 这个题仔细想想,就发现,取奇数的人有巨大的优势,因为假设 ...

  3. 福建工程学院第十四届ACM校赛B题题解

    第二集,未来的我发量这么捉急的吗 题意: 有n个数,请问有多少对数字(i,j)(1<=i<j<=n),满足(a[i]^a[j])+((a[i]&a[j])<<1) ...

  4. 福建工程学院第十四届ACM程序设计大赛 - E - 外传:小晋逃生记

    http://www.fjutacm.com/Contest.jsp?cid=705#P4 其实想清楚了就很简单,之前想了很多种方法,以为是二分什么的,看起来就像是一个单峰函数.但是发现直接暴力一波就 ...

  5. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  6. 湖南大学第十四届ACM程序设计新生杯(重现赛)G a+b+c+d=? (16进制与LL范围)

    链接:https://ac.nowcoder.com/acm/contest/338/G来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 32768K,其他语言65536K6 ...

  7. 湖南大学第十四届ACM程序设计新生杯(重现赛)I:II play with GG(博弈论||DP)

    链接:https://ac.nowcoder.com/acm/contest/338/I 来源:牛客网 题目描述 IG won the S championship and many people a ...

  8. 湖南大学第十四届ACM程序设计新生杯(重现赛)

    RANK  0 题数 0 期末复习没有参加,补几道喜欢的题. A: AFei Loves Magic  签到 思路 :不需考虑 碰撞 直接计算最终状态即可. #include<bits/stdc ...

  9. 湖南大学第十四届ACM程序设计新生杯 E.Easy Problem

    E.Easy Problem Description: Zghh likes number, but he doesn't like writing problem description. So h ...

随机推荐

  1. 学习笔记01:《开放平台产品成长之路-POP》

    当看到一些比较好的书籍和视频内容时,希望自己可以总价归纳下来,一方面是好的东西希望可以分享给大家,另一方面希望自己能很好的吸收并转化成掌握的知识,所以有了这个系列的学习笔记,共勉,今天的你比昨天更博学 ...

  2. 石川es6课程---7、数组

    石川es6课程---7.数组 一.总结 一句话总结: ^ 主要就map(映射:一个对一个),reduce(汇总:一堆出来一个),filter  过滤器,forEach 循环(迭代) 四个方法 ^ 使用 ...

  3. Ubuntu16.04下安装最新版本的CMake

      当前最新版CMake为3.9.1.. Ubuntu中更新cmake到最新版本,过程如下: 1. 卸载已经安装的旧版的CMake[非必需] apt-get autoremove cmake 2. 文 ...

  4. android data binding jetpack III 绑定一个方法

    第三篇 给view绑定一下方法响应. (补充:1.被绑定的方法必须是public的.   1.绑定方法可以用主语法.也可以用以下双冒号方式“::” android:onClick="@{pr ...

  5. java最常见的5个错误

    1. Null 的过度使用 避免过度使用 null 值是一个最佳实践.例如,更好的做法是让方法返回空的 array 或者 collection 而不是 null 值,因为这样可以防止程序抛出 Null ...

  6. ubuntu 设置qt程序开机启动

    1.建立一个桌面文件,forklift-app.desktop Name填写程序的名字 Exec执行程序的路径 [Desktop Entry] Version=1.0 Name=forklift-ap ...

  7. 【DataBase】mysql连接错误:Cannot get hostname for your address

    问题 环境:win7 + 64Bit + 本地mysql5.6 问题:navicat连接本地mysql数据库,提示“Cannot get hostname for your address”,但是连接 ...

  8. Tensorflow 从文件中载入训练数据

    本节包含: 用纯文本文件准备训练数据 加载文件中的训练数据 一.用纯文本文件准备训练数据 1.数据的数字化 比如,“是” —— “1”,“否” —— “0” “优”,“中”,“差” —— 1 2 3  ...

  9. 渗透测试 - KALI Linux 学习 - kali linux如何启动METASPLOIT服务

    kali 2.0 已经没有metasploit 这个服务了,所以service metasploit start 的方式不起作用. 在kali 2.0中启动带数据库支持的MSF方式如下: #1  首先 ...

  10. Django-ORM之ForeignKey的使用-多对一关系

    ForeignKey使用俩表示两张表多对一关系的外键,外键字段要定义在多属性的表中. 定义外键时,to的表可以直接写类名,但是需要注意类的定义顺序:也可以写字符串式的类名,这样就可以忽略class类的 ...