ACM-ICPC 2018 沈阳赛区网络预赛 I. Lattice's basics in digital electronics 哈希or字典树or暴力

版权声明:本博客内容基本为原创,如有问题欢迎联系,转载请注明出处 https://blog.csdn.net/qq_41955236/article/details/82533131

LATTICE is learning Digital Electronic Technology. He is talented, so he understood all those pieces of knowledge in 10−910^{-9}10−9 second. In the next 10−910^{-9}10−9 second, he built a data decoding device that decodes data encoded with his special binary coding rule to meaningful words.

His coding rule is called "prefix code", a type of code system (typically a variable-length code) distinguished by its possession of the "prefix property", which requires that there is no whole code word in the system that is a prefix (initial segment) of any other code word in the system. Note that his code is composed of only 000 and 111.

LATTICE's device only receives data that perfectly matches LATTICE's rules, in other words, people who send message to LATTICE will always obey his coding rule. However, in the process of receiving data, there are errors that cannot avoid, so LATTICE uses parity check to detect error bytes, after every 888-bit data there is 111 bit called parity bit, which should be '0' if there are odd number of '1's in the previous 888 bits and should be '1' if there are even number of '1's. If the parity bit does not meet the fact, then the whole 999 bits (including the parity bit) should be considered as invalid data and ignored. Data without parity bit is also considered as invalid data. Parity bits will be deleted after the parity check.

For example, consider the given data "101010101010101010101010", it should be divided into 333 parts:"101010101","010101010" and "101010". For the first part, there are 444 '1's in the first 888 bits, and parity bit is '1', so this part passed the check. For the second part, there are 444 '1's and parity bit is '0', so this part failed the check. For the third part, it has less than 999 bits so it contains no parity bit, so this part also failed the check. The data after parity check is "10101010", which is the first 888 bits of first part.

Data passed the parity check will go into a process that decodes LATTICE's code. The process is described in the following example: consider a situation that, "010" represents 'A' and "1011" represents 'B', if the data after parity check is "01010110101011010010", it can be divided into "010"+"1011"+"010"+"1011"+"010"+"010", which means "ABABAA" . LATTICE's device is so exquisite that it can decode all visible characters in the ASCII table .

LATTICE is famous for his Talk show, some reporters have sneaked into his mansion, they stole the data LATTICE to decode in hexadecimal, the coding rule consists of NNN pairs of corresponding relations from a bit string SiS_iSi​ to an ASCII code CiC_iCi​, and the message length MMM, they want to peek his privacy so they come to you to write a program that decodes messages that LATTICE receives.

Input

The first line an integer T (T<35)T\ (T<35)T (T<35) represents the number of test cases.

Every test case starts with one line containing two integers, M (0<M≤100000)M\ (0<M\leq100000)M (0<M≤100000), the number of original characters, and N (1≤N≤256)N\ (1\leq N \leq 256)N (1≤N≤256), then NNN lines, every line contains an integer CiC_iCi​, and a string Si(0<∣Si∣≤10)S_i(0<|S_i|\leq 10)Si​(0<∣Si​∣≤10), means that SiS_iSi​represents CiC_iCi​, the ASCII code to a visible character and SiS_iSi​ only contains '0' or '1' and there are no two numbers iii and jjj that SiS_iSi​ is prefix of SjS_jSj​.

Then one line contains data that is going to be received in hexadecimal. (0<∣data∣<200000)(0<|data|<200000)(0<∣data∣<200000).

Output

For each test case, output the decoded message in a new line, the length of the decoded message should be the same with the length of original characters, which means you can stop decoding having outputted MMM characters. Input guarantees that it will have no less than MMM valid characters and all given ASCII codes represent visible characters.

Hint

Lattice's encoding rule for test case 222:

ASCII code character lattice's code
494949 111 000100010001
505050 222 010010100101001
515151 333 011011011

the device takes this input in hex

 

1

14DB24722698

input in binary

 
xxxxxxxxxx

1

1

0001 0100 1101 1011 0010 0100 0111 0010 0010 0110 1001 1000

formatted into 666 lines, each line contains 888 data bits and one parity bit

 
xxxxxxxxxx

6

1

00010100 1

2

10110110 0

3

10010001 1

4

10010001 0

5

01101001 1

6

000

parity check of the third line and the last line failed, so ignore those two lines.parity bits should also be ignored.

 

4

1

00010100

2

10110110

3

10010001

4

01101001

arrange those bits by the rules informed

xxxxxxxxxx

1

1

0001 01001 011 011 01001 0001 011 01001

output the result

 
xxxxxxxxxx

1

1

12332132

样例输入

2
15 9
32 0100
33 11
100 1011
101 0110
104 1010
108 00
111 100
114 0111
119 0101
A6Fd021171c562Fde1
8 3
49 0001
50 01001
51 011
14DB24722698

样例输出

hello world!!!!
12332132

题意:

       给你n个密码,要你去破译一个被加密了的长度为m的字符。每个密码由一个字符的ASCII码和一个01字符串组成。然后给你一串加密后的字符,将字符(十六进制)先转化成二进制,然后每9个字符为一个单位(最后不满9位的也不算入答案),如果前8位字符中的‘1’的个数为奇数,第九位为‘0’或者‘1’的个数为偶数,第九位为‘1’,则这前8位为合法,可以被加入答案备选。最后处理出来的答案备选要与之前的密码对照,如上面的第二个样例 ,如果答案备选是000101101001011,且m=3, 那么前四位与49对应,5-7为与51对应,8-12位与50对应,最后的位则不要,因为答案长度为3,所以答案就是132.

       给你的密码一定合法,要你还原原字符。

做法:

       比赛的时候发现这道水题的时候已经没时间了,然后就写了一个纯暴力,然后T了。。。但是赛后改了一个匪夷所思的地方(把对‘a'的处理从-‘a’+10后for四次改成16个if else就过了。。喵了个咪),最后实测纯暴力是974ms。

       赛后在还没发现上面那个错误的时候又想到了字典树的做法(但是因为上面那个问题又T了。。气死了),然后就用132ms就过了。

       也参考了别的队的代码,是用哈希表做的,mp的第一维是长度,第二维是哈希出来的值,也是很神奇的处理方法,优化了不少82ms。


代码一:

  暴力

    974ms(险过。。)

#include<stdio.h>
#include<string>
#include<vector>
#include<map>
#include<iostream>
#include<string.h>
using namespace std;
#define pb push_back
char ans[100005],tmp[15],data[200005];
int len,anslen,lenxx;
char vis[2000005];
int xx[2000005];
map<string,int> mp;
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        len=0; anslen=0;
        lenxx=0;
        mp.clear();
        int n,m,x;
        scanf("%d%d",&m,&n);
        for(int i=1;i<=n;i++){
            int t;
            string zz;
            scanf("%d",&t);
            cin>>zz;
            mp[zz]=t;
        }
        scanf("%s",data);
        for(int i=0;i<strlen(data);i++){
            if(data[i]=='0'){
                xx[++lenxx]=0;xx[++lenxx]=0;xx[++lenxx]=0;xx[++lenxx]=0;
            }
            else if(data[i]=='1'){
                xx[++lenxx]=0;
                xx[++lenxx]=0;
                xx[++lenxx]=0;
                xx[++lenxx]=1;
            }
            else if(data[i]=='2'){
                xx[++lenxx]=0;xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=0;
            }
            else if(data[i]=='3'){
                xx[++lenxx]=0;xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=1;
            }
            else if(data[i]=='4'){
                xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=0;
            }
            else if(data[i]=='5'){
                xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=1;
            }
            else if(data[i]=='6'){
                xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=0;
            }
            else if(data[i]=='7'){
                xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=1;
            }
            else if(data[i]=='8'){
                xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=0;xx[++lenxx]=0;
            }
            else if(data[i]=='9'){
                xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=0;xx[++lenxx]=1;
            }
            else if(data[i]=='a'||data[i]=='A'){
                xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=0;
            }
            else if(data[i]=='b'||data[i]=='B'){
                xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=1;
            }
            else if(data[i]=='c'||data[i]=='C'){
                xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=0;
            }
            else if(data[i]=='d'||data[i]=='D'){
                xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=1;
            }
            else if(data[i]=='e'||data[i]=='E'){
                xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=0;
            }
            else if(data[i]=='f'||data[i]=='F'){
                xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=1;
            }
        }
        for(int i=1;i<=lenxx;i+=9){
            if(i+9>lenxx+1) break;
            int zz=0;
            for(int j=i;j<8+i;j++){
                if(xx[j]==1) zz++;
            }
            if(zz%2&&xx[i+8]==0||zz%2==0&&xx[i+8]==1){
                for(int z=i;z<i+8;z++){
                    vis[++len]=xx[z]+'0';
                }
            }
        }
        //printf("%s\n",vis+1);
        string tmp="";
        for(int i=1;i<=len;i++){
            tmp=tmp+vis[i];
            if(mp[tmp]){
                ans[anslen++]=(char)mp[tmp];
                tmp="";
                if(anslen==m) break;
            }
        }
        ans[anslen]='\0';
        printf("%s\n",ans);
    }
	return 0;
}

代码二:

   字典树

103ms

#include<stdio.h>
#include<string>
#include<iostream>
#include<string.h>
#include<map>
using namespace std;
#define pb push_back
char tmp[15],data[200005];
int len,anslen,lenxx;
char vis[1000005];
char xx[1000005];
int trie[1000005][2],sum[1000005],tot;
void Insert(char *s,int as){
    int len=strlen(s),rt=0;
    for(int i=0;i<len;i++){
        int aim=s[i]-'0';
        if(!trie[rt][aim]) trie[rt][aim]=++tot;
        if(i==len-1) sum[trie[rt][aim]]=as;
        rt=trie[rt][aim];
    }
}
int Search(char *s,int now,int &nex,int len){
    int rt=0;
    for(int i=now;i<len;i++){
        int aim=s[i]-'0';
        if(sum[trie[rt][aim]]){
            nex=i;
            return sum[trie[rt][aim]];
        }
        rt=trie[rt][aim];
    }
    return -1;
}
int main(){
    int t;
    char tmps[15];
    scanf("%d",&t);
    while(t--){
        memset(trie,0,sizeof(trie));
        memset(sum,0,sizeof(sum));
        tot=0;
        len=0; anslen=0;
        lenxx=0;
        int n,m,x;
        scanf("%d%d",&m,&n);
        for(int i=1;i<=n;i++){
            int tt;
            scanf("%d%s",&tt,tmps);
            Insert(tmps,tt);
        }
        scanf("%s",data);
        for(int i=0;i<strlen(data);i++){
            if(data[i]=='0'){
                xx[++lenxx]=0;xx[++lenxx]=0;xx[++lenxx]=0;xx[++lenxx]=0;
            }
            else if(data[i]=='1'){
                xx[++lenxx]=0;
                xx[++lenxx]=0;
                xx[++lenxx]=0;
                xx[++lenxx]=1;
            }
            else if(data[i]=='2'){
                xx[++lenxx]=0;xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=0;
            }
            else if(data[i]=='3'){
                xx[++lenxx]=0;xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=1;
            }
            else if(data[i]=='4'){
                xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=0;
            }
            else if(data[i]=='5'){
                xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=1;
            }
            else if(data[i]=='6'){
                xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=0;
            }
            else if(data[i]=='7'){
                xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=1;
            }
            else if(data[i]=='8'){
                xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=0;xx[++lenxx]=0;
            }
            else if(data[i]=='9'){
                xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=0;xx[++lenxx]=1;
            }
            else if(data[i]=='a'||data[i]=='A'){
                xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=0;
            }
            else if(data[i]=='b'||data[i]=='B'){
                xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=1;
            }
            else if(data[i]=='c'||data[i]=='C'){
                xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=0;
            }
            else if(data[i]=='d'||data[i]=='D'){
                xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=1;
            }
            else if(data[i]=='e'||data[i]=='E'){
                xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=0;
            }
            else if(data[i]=='f'||data[i]=='F'){
                xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=1;
            }
        }

        for(int i=1;i<=lenxx;i+=9){
            int zz=0;
            for(int j=i;j<8+i;j++){
                    if(xx[j]==1) zz++;
            }
            if(zz%2&&xx[8+i]==0||zz%2==0&&xx[8+i]==1){
                    for(int j=i;j<i+8;j++){
                        vis[++len]=xx[j]+'0';
                    }
            }
        }
        //printf("%s\n",vis+1);
        int no=1,ne,cas=0;
        while(1){
            int az=Search(vis,no,ne,len+1);
            printf("%c",az);
            if(++cas==m) break;
            no=ne+1;
        }
        printf("\n");
    }
	return 0;
}

代码三:

    哈希

81ms

#include<stdio.h>
#include<string.h>
using namespace std;
#define pb push_back
char ans[100005],tmp[15],data[200005];
int lenxx,anslen,len;
int vis[1000005],xx[1000005],mp[15][2005];
int a[12]={1,2,4,8,16,32,64,128,256,512,1024,2048};
int main(){
    int t;
    char tmps[15];
    scanf("%d",&t);
    while(t--){
        memset(mp,0,sizeof(mp));
        len=lenxx=0;
        int n,m,x;
        scanf("%d%d",&m,&n);
        for(int i=1;i<=n;i++){
            int tt,nn=0,l;
            scanf("%d%s",&tt,tmps);
            l=strlen(tmps);
            for(int j=0;j<l;j++){
                int wh=tmps[j]-'0';
                nn=nn+a[j]*wh;
            }
            mp[l][nn]=tt;
        }
        scanf("%s",data);
        
        for(int i=0;i<strlen(data);i++)
        {
            if(data[i]=='0'){
                xx[++lenxx]=0;xx[++lenxx]=0;xx[++lenxx]=0;xx[++lenxx]=0;
            }
            else if(data[i]=='1'){
                xx[++lenxx]=0;
                xx[++lenxx]=0;
                xx[++lenxx]=0;
                xx[++lenxx]=1;
            }
            else if(data[i]=='2'){
                xx[++lenxx]=0;xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=0;
            }
            else if(data[i]=='3'){
                xx[++lenxx]=0;xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=1;
            }
            else if(data[i]=='4'){
                xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=0;
            }
            else if(data[i]=='5'){
                xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=1;
            }
            else if(data[i]=='6'){
                xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=0;
            }
            else if(data[i]=='7'){
                xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=1;
            }
            else if(data[i]=='8'){
                xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=0;xx[++lenxx]=0;
            }
            else if(data[i]=='9'){
                xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=0;xx[++lenxx]=1;
            }
            else if(data[i]=='a'||data[i]=='A'){
                xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=0;
            }
            else if(data[i]=='b'||data[i]=='B'){
                xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=1;xx[++lenxx]=1;
            }
            else if(data[i]=='c'||data[i]=='C'){
                xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=0;
            }
            else if(data[i]=='d'||data[i]=='D'){
                xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=0;xx[++lenxx]=1;
            }
            else if(data[i]=='e'||data[i]=='E'){
                xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=0;
            }
            else if(data[i]=='f'||data[i]=='F'){
                xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=1;xx[++lenxx]=1;
            }
        }
        for(int i=1;i<=lenxx;i+=9){
            if(i+9>lenxx+1) break;
            int zz=0;
            for(int j=i;j<8+i;j++){
                if(xx[j]==1) zz++;
            }
            if(zz%2&&xx[i+8]==0||zz%2==0&&xx[i+8]==1){
                for(int z=i;z<i+8;z++){
                    vis[++len]=xx[z];
                }
            }
        }

        int lens=0,b=0,cas=0;
        for(int i=1;i<=len;i++){
            b+=vis[i]*a[lens++];
            if(mp[lens][b]){
                printf("%c",mp[lens][b]);
                if(++cas==m) break;
                lens=0,b=0;
            }
        }
        printf("\n");
    }
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41955236/article/details/82533131