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

P8085 [COCI2011-2012#4] KRIPTOGRAM 题解

时间:2024-02-29 22:55:28浏览次数:16  
标签:匹配 int 题解 KRIPTOGRAM cin 明文 P8085 哈希 字符串

P8085 [COCI2011-2012#4] KRIPTOGRAM 题解

本文原发布于2024-02-07洛谷题库 P8085 [COCI2011-2012#4] KRIPTOGRAM 题解区,现于2024-2-29转载至博客园

思路解析

这道题目的主要难点在于如何判断明文中形如 \(\texttt{a b c b}\) 的子串可以和密文 \(\texttt{b c a c}\) 匹配,因为如果单纯匹配字符的话将会无法匹配,所以我们需要找到一种新的储存一组明文和密文的方法。于是我们考虑存下上一个与当前字符串相同的字符串与当前字符串的距离,如果当前字符串在之前从来没出现过,就存下 \(0\)。这样下来我们就能正确的匹配明文和密文了。

接下来就要判断密文所对应的匹配数组是否在明文当中出现过,考虑使用滑动窗口做法。但由于删除子字符串会导致新的明文的匹配数组发生改变,所以我们需要同时存下来下一个与当前字符串相同的字符串的位置。原因是如果删掉一个明文的子字符串就会导致下一个与当前字符串相同的字符串的匹配数组的值变为 \(0\)。

最后我们就需要把已经求出来的两个匹配数组进行判断比较,但是如果对于每一个明文的子字符串都从头到尾比较一次的话时间复杂度就会达到 \(O((10^6)^2)\),显然会 \(\text{TLE}\),于是就要使用字符串哈希进行优化,如果没学过字符串哈希的可以去看这道题自学一下 P3370 【模板】字符串哈希。删除滑动窗口头部的元素相当于将哈希值减去元素的值 \(\times\) 它对应数位的权值,将滑动窗口右移则相当于将哈希值 \(\times BASE\),添加尾部的新元素则是将哈希值直接加上元素的值,而对于元素的修改就是减去原来的,然后加上修改后的值。

code

#include<bits/stdc++.h>
using namespace std;
#define ull unsigned long long
const int N = 1e6 + 10;
const ull P = 13331;
string a[N], b[N];
ull p[N], l1[N], l2[N], t1[N];
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	string s1, s2;
	int n1 = 1, n2 = 1;
	cin >> s1;
	for(; s1 != "$"; n1++) {
		a[n1] = (s1);
		cin >> s1;
	}
	cin >> s2;
	for(; s2 != "$"; n2++) {
		b[n2] = (s2);
		cin >> s2;
	}
	n1--; n2--;
	p[0] = 1;
	for(int i = 1; i <= n1; i++) {
		p[i] = p[i - 1] * P;
	}
	map<string, int> mp1, mp2;
	ull h1 = 0, h2 = 0;
	for(int i = 1; i <= n2; i++) {
		if(mp1[a[i]] != 0) {
			l1[i] = i - mp1[a[i]];
			t1[mp1[a[i]]] = i;
		}
		else l1[i] = 0;
		mp1[a[i]] = i;
		h1 = h1 * P + l1[i];

		if(mp2[b[i]] != 0) {
			l2[i] = i - mp2[b[i]];
		}
		else l2[i] = 0;
		mp2[b[i]] = i;
		h2 = h2 * P + l2[i];
	}
	if(h1 == h2) {
		cout << 1;
		return 0;
	}
	for(int i = 2; i + n2 - 1 <= n1; i++) {
		int r = i + n2 - 1;
		h1 = (h1 - l1[i - 1] * p[n2 - 1]) * P;
		if(mp1[a[i - 1]] == i - 1) {
			mp1[a[i - 1]] = 0;
		}
		if(t1[i - 1] != 0) {
			h1 -= l1[t1[i - 1]] * p[r - t1[i - 1]];
			l1[t1[i - 1]] = 0;
		}
		if(mp1[a[r]] != 0) {
			l1[r] = r - mp1[a[r]];
			t1[mp1[a[r]]] = r;
		} 
		else l1[r] = 0;
		mp1[a[r]] = r;
		h1 += l1[r];
		if(h1 == h2) {
			cout << i;
			return 0;
		}
	}
	return 0;
}

标签:匹配,int,题解,KRIPTOGRAM,cin,明文,P8085,哈希,字符串
From: https://www.cnblogs.com/2020luke/p/18045773

相关文章

  • 个人题解:江苏省选 2019 第二轮
    精准预测我们首先发现每个人每个时刻只有生死,所以我们可以建一个2-sat模型。每个人对应\(T+1\)个节点,表示这个人在每个时刻的生死。那么,题目的条件可以直接在这个模型上面建图,还要注意第\(t\)秒死亡可推出第\(t+1\)秒死亡和第\(t+1\)秒存活能推出第\(t\)秒存活的两......
  • 后端项目打包相关问题解决
    在对项目进行打包后,我运行jar包发现出现下面错误:nomainmanifestattribute,in"app.jar" 在“app.jar”中没有主清单属性说明jar包里面的META-INF/MANIFEST.MF文件中没有Main-Class这个属性于是我解压jar包,到META-INF/MANIFEST.MF文件中手动添加了Main-Class: com.xxx.xx......
  • 2024年2月29号题解
    P1014[NOIP1999普及组]Cantor表解题思路和之前的蛇蝎矩阵很像,因此可以先构建一个蛇蝎矩阵因为是z形所以在每个奇数次矩阵的对角线进行交换就可以了,这样就得到了我们需要的矩阵代码实现#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<stdlib.h>#inclu......
  • 题解 CF1709 XOR
    *2400*dsuontree一道很好的题目思路很巧妙传送门题目大意给出一棵树,\(n\)个节点,每个节点有权值\(v\),定义一次操作为修改任意一个节点的值为任意正整数,要求最后的树不存在任意简单路径使得路径异或和为\(0\)Solution一个很常用的套路,先钦定根节点为\(1\)定义\(w......
  • CF1265E Beautiful Mirrors 题解
    CF1265EBeautifulMirrors题解题目大意题目传送门你有\(n\)个点,当你在第\(i\)个点时,有\(p_i\)的概率到达点\(i+1\),有\(1-p_i\)的概率回到点1。当到达点\(n+1\)时,游戏结束。且期望进行的游戏次数。\(1\len\le2\times10^5\)。题目分析设\(f_i\)表示到达点\(......
  • P2606 [ZJOI2010] 排列计数 题解
    题意:求有多少个排列满足:对于每一个\(2\lei\len\),\(a_i>a_{\frac{i}{2}}\)。首先我们会发现这些数之间的大小关系形成了一个完全二叉树,因为每一个\(a_i\)都必须小于\(a_{2\timesi}\)和\(a_{2\timesi+1}\)。会发现本题的方案和每个位置具体的值并没有关系,而只......
  • 打击犯罪(题解)
    题目题目描述样例输入722531342242233167257256样例输出1关于本题这个题反着想会很简单,也就是复活犯罪,但是这个反着的思路不好想到(比如我就没想到)。看其他blog基本上都是反着来的,确实复杂度小不少,但是别人写过的我就不写了,我就给出正着来的解......
  • [ABC282Ex] Min + Sum 题解
    [ABC282Ex]Min+Sum题解题面传送门。题目要求有多少对\((l,r)\)满足\(1\lel\ler\len\)且\(\sum_{i=l}^{r}{b_i}+\min_{i=l}^{r}{a_i}\leS\)。考虑CDQ分治,那么我们需要不断寻找有多少对\((l,r)\)满足\(L\lel\leM<r\leR\)且\(\sum_{i=l}^{r}{b......
  • P9836 种树 题解
    题目传送门前置知识质因数分解。贪心。题解思路先来解决一个问题,统计一个数\(x\)的正因数个数。可以将\(x\)质因数分解,得到每个数在\(x\)的质因数分解中出现了多少次。都知道质因数分解是每个数的唯一分解,那么统计个数的时候就只需要枚举每个质因数的出现个数。所以......
  • CF510C Fox And Names 题解
    CF510CFoxAndNames题解https://www.luogu.com.cn/problem/CF510C思路题意就是:确定一个小写字母的比较规则,使得给定的所有字符串在一开始就是按你确定的比较规则排序了的。可以发现:对于前后一对字符串,找到第一对不同的字符,是要这两个字符有合法的大小关系,就能满足题意。......