首页 > 其他分享 >题解 P8085 [COCI2011-2012#4] KRIPTOGRAM

题解 P8085 [COCI2011-2012#4] KRIPTOGRAM

时间:2023-08-07 09:33:45浏览次数:65  
标签:typedef 题解 LL KRIPTOGRAM long P8085 while 字符串

题目链接

题目问的是相对位置是否一样,即若 \(s\) 的第 \(1,2,3\) 个字符串相等,\(t\) 的第 \(1,2,3\) 个字符串也相等,则 \(s=t\)。

由于 \(t\) 的长度是固定的,所以我们使用哈希进行快速匹配。

那么如何设计哈希函数则成为本题的难点。

由于问相对位置,那么可以记 \(val[i]\) 表示第 \(i\) 个字符串上上一个相等的字符串间隔的距离,如果是第一个,则设置为 \(\infty\),这样就能表示出关系了。

点击查看代码
#include<bits/stdc++.h>
using namespace std;

typedef unsigned long long ULL;
typedef long long LL;

LL read() {
    LL sum=0,flag=1; char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') flag=-1; c=getchar();}
    while(c>='0'&&c<='9') {sum=sum*10+c-'0'; c=getchar();}
    return sum*flag;
}

const int N=1e6+10;
const LL MOD1=998244353,MOD2=1e9+7,Base=13331,INF=1e9;
int n,m;
int val1[N],val2[N],nxt[N];
string s[N],t[N];
LL p1[N],p2[N];
LL hs1,hs2,ht1,ht2;
map<string,int> mp;

int main() {
    while(cin>>s[++n]) {
        if(s[n]=="$") {
            n--;
            break;
        }
    }
    while(cin>>t[++m]) {
        if(t[m]=="$"){
            m--;
            break;
        }
    }
    
    for(int i=1;i<=n;i++) {
        if(mp[s[i]]!=0) {
            val1[i]=i-mp[s[i]];
            nxt[mp[s[i]]]=i;
        }
        else {
            val1[i]=INF;
        }
        mp[s[i]]=i;
        if(i<=m) {
            hs1=(hs1*Base+val1[i])%MOD1;
            hs2=(hs2*Base+val1[i])%MOD2;
        }
    }
    mp.clear();
    p1[0]=1; p2[0]=1;
    for(int i=1;i<=m;i++) {
        if(mp[t[i]]!=0) {
            val2[i]=i-mp[t[i]];
        }
        else {
            val2[i]=INF;
        }
        mp[t[i]]=i;
        ht1=(ht1*Base+val2[i])%MOD1;
        ht2=(ht2*Base+val2[i])%MOD2;
        p1[i]=p1[i-1]*Base%MOD1;
        p2[i]=p2[i-1]*Base%MOD2;
    }
    if(hs1==ht1&&hs2==ht2) {
        cout<<1<<endl; return 0;
    }

    for(int i=2;i+m-1<=n;i++) {
        // for(int j=1;j<=n;j++) cout<<val1[j]<<' ';
        // cout<<endl;
        hs1=((hs1-val1[i-1]*p1[m-1])%MOD1+MOD1)%MOD1;
        hs2=((hs2-val1[i-1]*p2[m-1])%MOD2+MOD2)%MOD2;
        hs1=(hs1*Base+val1[i+m-1])%MOD1;
        hs2=(hs2*Base+val1[i+m-1])%MOD2;
        if(nxt[i-1]<=i+m-1) {
            int l=i+m-1-nxt[i-1];
            hs1=((hs1-val1[nxt[i-1]]*p1[l])%MOD1+MOD1)%MOD1;
            hs2=((hs2-val1[nxt[i-1]]*p2[l])%MOD2+MOD2)%MOD2;
            hs1=((hs1+INF*p1[l])%MOD1+MOD1)%MOD1;
            hs2=((hs2+INF*p2[l])%MOD2+MOD2)%MOD2;
        }
        val1[nxt[i-1]]=INF;
        if(hs1==ht1&&hs2==ht2) {
            cout<<i;
            return 0;
        }
    }
    
    return 0;
}

标签:typedef,题解,LL,KRIPTOGRAM,long,P8085,while,字符串
From: https://www.cnblogs.com/zhangyuzhe/p/17610624.html

相关文章

  • 『MGOI』Simple Round I | B. 魔法照相馆 题解
    题目传送门一道模拟题。并不复杂的模拟题,也不需要用到贪心。我们可以创建一个数组来记录每个幕布是否被拉上,统计答案的时候,就看看这块幕布前面有多少个没拉上的,最后如果这块幕布拉上了,就重新放下来就行了。#include<bits/stdc++.h>#definelllonglong#defineINF1e9usi......
  • 【题解】Codeforces Round 890(CF1856)
    赛时过了A-E1,rk195可惜是E2傻逼了不会背包优化了,直接连普及组水平都不到了。A.TalesofaSort题目描述:给定长度为\(n\)的序列\(a\),每次操作为对于所有\(i\)将\(a_i\)变为\(\max(a_i-1,0)\),询问最少多少次操作之后可以让序列\(a\)单调不降。题目分析:唯一能改变......
  • 【题解】Luogu[P9504] 『MGOI』Simple Round I C. 魔法禁林
    Link这题我们发现如果直接去枚举生命和法力值显然是不行的,又看到说最小的生命值,不禁想到最短路,但是怎么跑?我们令经过一条边之前魔力值为\(k\),那么该边的边权为\(\lfloor\dfrac{w}{k}\rfloor\),于是我们讲题目转化为了边权为\(\lfloor\dfrac{w}{k}\rfloor\)时\(s\)到\(t\)......
  • [ABC310] D~F 题解
    [ABC310]D~F题解D-PeacefulTeams暴力搜索,搜索每个人在的队伍,为了去重,在一个人第一次加入新的队伍之后跳出。bitset<N>st;voiddfs(intu){for(inti=1;i<=m;i++)if(pos[a[i]]&&pos[b[i]]&&pos[a[i]]==pos[b[i]])return;if(u>n)......
  • C++动态规划经典试题解析之打家劫舍系列
    1.前言力扣上有几道与打家劫舍相关的题目,算是学习动态规划时常被提及的经典试题,很有代表性,常在因内大大小小的社区内看到众人对此类问题的讨论。学习最好的方式便是归纳总结、借鉴消化,基于这个目的,本文对此类问题也做了讲解,在一些优秀思想的基础上添加了个人观点。闲话少说,进入......
  • P9499 「RiOI-2」change 题解--zhengjun
    思维妙妙题。赛时的错误做法:找到每个点往后进位变优的位置,最多\(O(\log)\)个;然后从前往后能变优就变优,往后贪心进位。hack数据:0133510021022输出:100这样子由于\(1\)到\(2\)不优,而\(1\)到\(3\)个数不够,所以导致无法进位到\(3\)。所以加强一下......
  • CentOS8安装Docker报错问题解决
    问题描述CentOS版本:8.5.2111。#cat/etc/redhat-releaseCentOSLinuxrelease8.5.2111安装准备:#安装所需软件包sudoyuminstall-yyum-utilsdevice-mapper-persistent-datalvm2#设置docker仓库:推荐阿里云sudoyum-config-manager--add-repohttp://mirrors.al......
  • Codeforces Round 890 (Div. 2) supported by Constructor Institute 题解
    A.TalesofaSort关键就是找逆序对记一组逆序对下标为\(l,r\),则求出最大的\(a_l\)即可B.GoodArrays记要构造的GoodArray为\(b\)前置:\(\forall1\lei\len,b_i=1\)然后\(O(n)\)扫一遍看一下有没有重复,有重复就\(b_i\leftarrowb_i+1\)扫完之后,记\(sum=\sum_......
  • Codeforces Round 882 (Div. 2) 题解
    A.TheManwhobecameaGod求出相邻两个元素的差值,去掉前\(m\)个大的差值以后的差值和即为答案B.HamonOdyssey由按位与的性质可以知道,前缀与和的值只会越来越小,只要和为\(0\)的时候我们就清空按位与前缀和,增加一下次数,如果最终次数不为\(0\),特判一下,次数加一即可C.......
  • abc313D 题解
    [abc313DOddorEven]。好有趣捏。我们考虑\(N=K+1\)。设\(s_i\)为\(\displaystyle\sum_{j\neqi}a_j\bmod2\)。因为\(K\)为奇数,我们可以得到\(\displaystyle\sum_{i=1}^{K+1}s_i\equiv\sum_{i=1}^{K+1}a_i\pmod2\)。所以\(a_i=\displaystyle\sum_{i=1}^{K+1}a_i\b......