破译密码

Description
大意就是:给n条01信息以及m条01密码,
求对于每条密码,
有多少条信息与他的最长公共前缀=min(密码长度,该条信息长度),
1<=N,M<=50000,其长度均小于等于10000
输入的总长度<=500000
Input
第1行输入N和M
之后N行描述秘密信息,
之后M行描述密码.
每行先输入一个整数表示信息或密码的长度,之后输入这个信息或密码.所有数字之间都用空格隔开.
Output
共M行,输出每条密码的匹配信息数.
Sample Input
4 5  //4条信息,5组密码
3 0 1 0  //第一条信息,长度为3,信息为010
1 1
3 1 0 0
3 1 1 0
1 0  //第一条密码,长度为1,密码为0
1 1
2 0 1
5 0 1 0 0 1
2 1 1
Sample Output
1  //0是010的前缀
3  //1是1,100,110的前缀
1  //01是010的前缀
1  //010是01001的前缀
2  //1是11的前缀,11是110的前缀

sol:先将读入的信息串建立Trie树,本题信息可能是密码的前缀,密码也可能是信息的前缀。难点是怎样判断对于某个串,别人是它的前缀,它又是别人的前缀呢?如:

我们对每个点进行标记:

longer[i],记录第i个结点,有多少个单词经过了它,即它被经过了多少次。

shorter[i],记录以第i个结点为结束位置的的单词数。

在进行查找时,依次查找密码的每一个字符,若当前字符不是最后一个字符,则ans+shorter[i](某些信息是该密码的前缀),否则ans+longer[i](该密码查找结束,该密码是信息的前缀)。

代码如下:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 #define maxn 500500
 6 int n,m,tmp,cnt;
 7 int son[maxn][2],a[10100],longer[maxn],shorter[maxn];
 8
 9 void insert()
10 {
11     int p=0;
12     for (int i=1;i<=tmp;i++)
13     {
14         if (!son[p][a[i]])
15             son[p][a[i]]=++cnt;
16         p=son[p][a[i]];
17         longer[p]++;
18         //p这个点被经过多少次
19     }
20     shorter[p]++;
21     //以P为结束端点的单词有多少个
22 }
23
24 void work(){
25     int p=0,ans=0;
26     for (int i=1;i<=tmp;i++)
27     {
28         if (!son[p][a[i]])
29             break;
30         if (i<tmp)
31             ans+=shorter[son[p][a[i]]];
32             //如果i<tmp说明当前读的单词还没有走完,此时经过的点
33             //加上其shorter标记,说是这些单词都是他的前缀
34         else
35             ans+=longer[son[p][a[i]]];
36             //否则说是当前读的单词已走完,此时经过的点被经过了
37             //多少次,就说当前单词是其前缀
38         p=son[p][a[i]];
39     }
40     printf("%d\n",ans);
41 }
42
43 int main(){
44     scanf("%d%d",&n,&m);
45     for (int i=1;i<=n;i++)
46     {
47         scanf("%d",&tmp);
48         for (int j=1;j<=tmp;j++)
49              scanf("%d",&a[j]);
50         insert();
51     }
52     for (int i=1;i<=m;i++)
53     {
54         scanf("%d",&tmp);
55         for (int j=1;j<=tmp;j++)
56              scanf("%d",&a[j]);
57         work();
58     }
59     return 0;
60 }

原文地址:https://www.cnblogs.com/cutepota/p/12590002.html

时间: 2024-10-07 05:09:45

破译密码的相关文章

HDU1287 破译密码

问题链接:HDU1287 破译密码.基础训练级的题,用C语言编写程序. C语言中,异或运算符是"^".对于源码a,加密字母x,密文字母v,根据题意满足:a^x=v,那么有a^x^x=v^x,得a=v^x.对于所有的v,用"A"到"Z"作为x去试算,满足v^x为"A"到"Z"即为加密字母x. 试探法寻找密码用大写字母是需要找到一个字母x,满足对于所有数据计算结果都为大写字母. AC的C语言程序如下: /* H

Linux发行版Debian操作系统破译密码

Linux发行版Debian操作系统破译密码 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 其实玩过Linux的小伙伴,对破解服务器密码都应该有所了解,典型的两个代表,我觉得一个是Centos6.x版本网上和Ubantu15.04版本网上都是很适合大家去玩的,只要把这2个操作系统玩熟了,其他的操作系统都是手到擒来的事情.服务器端我推荐使用Centos发型版本,至于个人用户的话我推荐Ubantu,因为用户会更注重体验,而服务器更注重稳定嘛,哈哈~ 我写这篇博客,就是因为我们的一

杭电ACM1287——破译密码

这题,简单的异或运算. a ^ b = c  => a ^ b ^ a = c ^ a = b. 而这个b就是我们要求解的. 下面的是AC的代码: #include <iostream> #include <cstring> using namespace std; int a[10010]; char b[10010]; int main() { int n; int i, j, k; while(cin >> n) { for(i = 0; i < n;

十个破译密码方法

个人网络密码安全是整个网络安全的一个重要环节,如果个人密码遭到黑客破解,将引起非常严重的后果,例如网络银行的存款被转账盗用,网络游戏内的装备或者财产被盗,QQ币被盗用等等,增强网民的网络安全意识是网络普及进程的一个重要环节,因此,在网民采取安全措施保护自己的网络密码之前,有必要了解一下流行的网络密码的破解方法,方能对症下药,以下是我总结的十个主要的网络密码破解方法. 1.暴力穷举 密码破解技术中最基本的就是暴力破解,也叫密码穷举.如果黑客事先知道了账户号码,如邮件帐号.QQ用户帐号.网上银行账号

MCMC 破译密码 http://mlwhiz.com/blog/2015/08/21/MCMC_Algorithms_Cryptography/

# AIM: To Decrypt a text using MCMC approach. i.e. find decryption key which we will call cipher from now on. import string import math import random # This function takes as input a decryption key and creates a dict for key where each letter in the

学术休假-破译密码

蛋收到了两串加密的密码:破解的规则是:现将两串密码的数字提取出来,再将上下的数字进行相加,不够的将用0代替,最后的数字再加上70得到字母的ASCII码值,最后求出密码. 例如: 样例输入: @#GHt1GG6gB70h)*4^2!*6 %G5=j6%[email protected] 1 6 7 0 4 2 6 5 6 3 6 0 ============= 6 12 10 6 4 2 6 样例输出: LRPLJHL /* *Copyright (c) 2015,烟台大学计算机学院 *All g

POJ3749 破译密码

Description 据说最早的密码来自于罗马的凯撒大帝.消息加密的办法是:对消息原文中的每个字母,分别用该字母之后的第5个字母替换(例如:消息原文中的每个字母A都分别替换成字母F).而你要获得消息原文,也就是要将这个过程反过来. 密码字母:A B C D E F G H I J K L M N O P Q R S T U V W X Y Z M 原文字母:V W X Y Z A B C D E F G H I J K L M N O P Q R S T U 注意:只有字母会发生替换,其他非字

HDU ACM 1287 破译密码

直接枚举即可 #include<iostream> using namespace std; int main() { int n,i,j; int a[10001]; char s; while(cin>>n) { for(i=0;i<n;i++) cin>>a[i]; for(i=0;i<26;i++) { s=i+'A'; for(j=0;j<n;j++) if((a[j]^s) <'A' || (a[j]^s) >'Z') brea

潜伏者

题目描述 R 国和 S 国正陷入战火之中,双方都互派间谍,潜入对方内部,伺机行动.历尽艰险后,潜伏于 S 国的 R 国间谍小 C 终于摸清了 S 国军用密码的编码规则: 1. S 国军方内部欲发送的原信息经过加密后在网络上发送,原信息的内容与加密后所得的内容均由大写字母‘A’-‘Z’构成(无空格等其他字符). 2. S 国对于每个字母规定了对应的“密字”.加密的过程就是将原信息中的所有字母替换为其对应的“密字”. 3. 每个字母只对应一个唯一的“密字”,不同的字母对应不同的“密字”.“密字”可以