zoukankan      html  css  js  c++  java
  • 福建工程学院第十四届ACM校赛J题题解

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

    题意:

    给你两个只包含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 = 150000;
    
    ll a[N],b[N];
    
    const ll PMOD=(479<<21)+1;
    
    const ll PR=3;
    
    static ll qp[30];
    
    ll res[N];
    
    struct NTT__container
    
    {
    
        NTT__container()
    
        {
    
            int  t,i;
    
            for( i=0; i<21; i++)///注意循环上界与2n次幂上界相同
    
            {
    
                t=1<<i;
    
                qp[i]=quick_pow(PR,(PMOD-1)/t);
    
            }
    
        }
    
        ll quick_pow(ll x,ll n)
    
        {
    
            ll ans=1;
    
            while(n)
    
            {
    
                if(n&1)
    
                    ans=ans*x%PMOD;
    
                x=x*x%PMOD;
    
                n>>=1;
    
            }
    
            return ans;
    
        }
    
        int get_len(int n)///计算刚好比n大的2的N次幂
    
        {
    
            int i,len;
    
            for(i=(1<<30); i; i>>=1)
    
            {
    
                if(n&i)
    
                {
    
                    len=(i<<1);
    
                    break;
    
                }
    
            }
    
            return len;
    
        }
    
        inline void NTT(ll F[],int len,int type)
    
        {
    
            int id=0,h,j,k,t,i;
    
            ll E,u,v;
    
            for(i=0,t=0; i<len; i++)
    
            {
    
                if(i>t)   swap(F[i],F[t]);
    
                for(j=(len>>1); (t^=j)<j; j>>=1);
    
            }
    
            for( h=2; h<=len; h<<=1)
    
            {
    
                id++;
    
                for( j=0; j<len; j+=h)
    
                {
    
                    E=1;
    
                    for(int k=j; k<j+h/2; k++)
    
                    {
    
                        u=F[k];
    
                        v=(E*F[k+h/2])%PMOD;
    
                        F[k]=(u+v)%PMOD;
    
                        F[k+h/2]=((u-v)%PMOD+PMOD)%PMOD;
    
                        E=(E*qp[id])%PMOD;
    
                    }
    
                }
    
            }
    
            if(type==-1)
    
            {
    
                int i;
    
                ll inv;
    
                for(i=1; i<len/2; i++)
    
                    swap(F[i],F[len-i]);
    
                inv=quick_pow(len,PMOD-2);
    
                for( i=0; i<len; i++)
    
                    F[i]=(F[i]%PMOD*inv)%PMOD;
    
            }
    
        }
    
        inline void inv(ll *a,int len)///答案存在res中
    
        {
    
            if(len==1)
    
            {
    
                res[0]=quick_pow(a[0],PMOD-2);
    
                return ;
    
            }
    
            inv(a,len>>1);///递归
    
            static ll temp[N];
    
            memcpy(temp,a,sizeof(ll)*(len>>1));
    
            NTT(temp,len,1);
    
            NTT(res,len,1);
    
            int i;
    
            for(i=0; i<len; i++)
    
                res[i]=res[i]*(2-temp[i]*res[i]%PMOD+PMOD)%PMOD;
    
            NTT(res,len,-1);
    
            memset(res+(len>>1),0,sizeof(ll)*(len>>1));
    
        }
    
        void mul(ll x[],ll y[],int len)///答案存在x中
    
        {
    
            int i;
    
            NTT(x,len,1);///先映射到频域上
    
            NTT(y,len,1);///先映射到频域上
    
            for(i=0; i<len; i++)
    
                x[i]=(x[i]*y[i])%PMOD;///在频域上点积
    
            NTT(x,len,-1);///再逆变换回时域
    
        }
    
     
    
    } cal;
    
    ll x[N],y[N],z[N];
    
    int main()
    
    {
    
        ios::sync_with_stdio(false);
    
        cin.tie(0);
    
        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,0,len*sizeof(ll));
    
            memset(y,0,len*sizeof(ll));
    
            memset(z,0,len*sizeof(ll));
    
            for(int i=0;i<s1.length();i++){
    
                x[i]=s1[i]-'0';
    
            }
    
            for(int i=0;i<s2.length();i++){
    
                y[i]=s2[i]-'0';
    
            }
    
            reverse(y,y+s2.length());
    
            cal.mul(x,y,len);
    
            //for(int i=0;i<len;i++)
    
            for(int i=s2.length()-1;i<s1.length();i++)
    
                z[i]+=x[i];
    
            //做0匹配
    
            memset(x,0,len*sizeof(ll));
    
            memset(y,0,len*sizeof(ll));
    
            for(int i=0;i<s1.length();i++){
    
                x[i]=1-(s1[i]-'0');
    
            }
    
            for(int i=0;i<s2.length();i++){
    
                y[i]=1-(s2[i]-'0');
    
            }
    
            reverse(y,y+s2.length());
    
            cal.mul(x,y,len);
    
            //for(int i=0;i<len;i++)
    
            for(int i=s2.length()-1;i<s1.length();i++)
    
                z[i]+=x[i];
    
     
    
            bool flag=0;
    
            for(int i=s2.length()-1;i<s1.length();i++){
    
                if(z[i]>=s2.length()-1){
    
                    flag=1;
    
                    break;
    
                }
    
            }
    
            if(flag){
    
                puts("YES");
    
            }
    
            else {
    
                puts("NO");
    
            }
    
        }
    
    }
  • 相关阅读:
    Smobiler实现手机弹窗
    在 ASP.NET Web API 中使用 Attribute 统一处理异常
    VMWare的网络模式说明
    Windows Server2008 IIS通过Nginx实现绑定多个https域名
    Error while Launching activity
    Android 动态渐变按钮
    mysql安装和配置详解以及Navicat连接失败问题
    selenium的基础学习
    使用Pandas.read_csv时出现OSError: Initializing from file failed
    sklearn 机器学习 Pipeline 模板
  • 原文地址:https://www.cnblogs.com/xseventh/p/10878253.html
Copyright © 2011-2022 走看看