ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

L.Let's Swap 找规律+字符串双哈希

2022-07-14 19:04:35  阅读:169  来源: 互联网

标签:AB 或者 long maxn Swap 哈希 操作 字符串 Let


(这道题赛后补的,就是说现场根本没有时间开到www

依据题意,有两种操作,过程还蛮复杂的,又倒置又反转,然后我看到这种操作一般就懵逼了,然后捏?

这时候一般就需要手%啥的,就是画图模拟,找规律,一般都有一些”性质“的

比如这题的一些性质:

#同一个操作使用两次,会撤销,相当于没有操作

那么..设想操作A,B组成了一个序列,这个序列只能是:

ABABABA....

BABABAB....

#那么AB操作,实质上是什么呐?

画图可知,一次ab或者ba,相当于把字符串向左或者向右移动 abs(L1-L2),若干次操作ab(ba),相当于把字符串向左或者向右移动若干次

题解在这边写的是d=gcd(s.length(),L1-L2),最多位移n/d次,在这边看了好久,自己推了一下应该是因为:

 

 

那么我们就可以判断T是否是S经过若干次位移得到的——用kmp或者字符串哈希

kmp(这玩意学一次忘一次,每次用到都得重新学x,干脆写Hash:

字符串Hash的思想要是不明白的话左转某谷或者某dn哇~

想记录一下实现的细节:

比如要把T扩展成2倍,因为我们肯定要涉及到末尾取一部分+前面的一部分合并起来,展开成两倍可以实现

然后循环n次(最多位移n次吧,不过这个应该是为了保证不错,有往上放大过的数值了),判断Hash值相等不相等~

又因为有B(AB)(AB)(AB)

或者A(AB)(AB)(AB)

或者(AB)(AB)S

三种情况分别试一下

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+7;
const long long mod=1e9+7;
string s,t,tmp;
long long ss[maxn],ss1[maxn],tt[maxn],tt1[maxn],p[maxn],p1[maxn];
int len,totlen,l1,l2;
bool check( )
{

    for(int i=0;i<totlen;i++){
        ss[i+1]=(ss[i]*31%mod+(tmp[i]-'a'+1)%mod+mod)%mod;
        ss1[i+1]=(ss1[i]*29%mod+(tmp[i]-'a'+1)%mod+mod)%mod;
    }
    //double hash 


    int cnt=totlen,pos=totlen,flag=0;
    
        //最多移位n次,这里有点暴力枚举了 
        while(cnt){
            pos%=2*totlen;
            while(pos<totlen) pos+=len;
        
            if((tt[pos]-tt[pos-totlen]*p[totlen]%mod+mod)%mod==ss[totlen]&&
               (tt1[pos]-tt1[pos-totlen]*p1[totlen]%mod+mod)%mod==ss1[totlen])
               {
                    flag=1;break;
               }
            pos+=len;
            cnt--;
        } 
        return flag;
}
void solve(){
    //ababab,delta=gcd(l1-l2)
    totlen=s.length();
    len=abs(l1-l2);
    
    t=t+t;
    
    for(int i=0;i<2*totlen;i++){
        tt[i+1]=(tt[i]*31%mod+(t[i]-'a'+1)%mod+mod)%mod;
        tt1[i+1]=(tt1[i]*29%mod+(t[i]-'a'+1)%mod+mod)%mod;
    }
    
    tmp=s;

    if(    check() ) {
        cout<<"yes"<<endl;
        return;
    }
    
    tmp=s.substr(l1)+s.substr(0,l1);
    reverse(tmp.begin(),tmp.end());

    if(    check() ) {
        cout<<"yes"<<endl;
        return;
    }
    
    
    tmp=s.substr(l2)+s.substr(0,l2);
    reverse(tmp.begin(),tmp.end());

    if(    check() ) {
        cout<<"yes"<<endl;
        return;
    }
    
    cout<<"no"<<endl;
    return;
}
int main()
{
    //freopen("lys.in","r",stdin);
    
    p[0]=1;p1[0]=1;
    for(int i=1;i<maxn-2;i++)
    {
        p[i]=p[i-1]*31%mod;p1[i]=p1[i-1]*29%mod;
    }
    
    
    int q;
    cin>>q;
    while(q--){
        cin>>s;
        cin>>t;
        cin>>l1>>l2;
        solve();
    }
}

 

标签:AB,或者,long,maxn,Swap,哈希,操作,字符串,Let
来源: https://www.cnblogs.com/liyishui2003/p/16478973.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有