1. 程式人生 > >jzoj 2937_監聽還原_KMP

jzoj 2937_監聽還原_KMP

sin out text 沒有 std break 英文 很難 nbsp

題目描述

Alice和Bob正在悄悄地給對方發信息,信息都是由英文小寫字母組成的,他們約定,所有的字母都得經過一個字母表進行變換,以防泄漏。另一方面John卻在監聽。

John發現,Alice和Bob通信的時候,總是先發送加密後的密文,然後緊接著發送原文。

但是Alice和Bob似乎也意識到了似乎有人監聽,有時候會隨意中斷了他們的通信。不過每次都是在發送完密文之後才停止傳送的。也就是說,John截獲到的信息是密文的全文以及前一部分原文。原文可能一個字符都沒有,也可能原文的全文都被截獲。

現在John比較頭疼,他雖然已經得到了他們兩個人通信的加密字母表,但是分不清楚什麽地方是密文和明文的分界線。你能幫他還原回完整的傳輸內容嗎?

如果有多種可能時,John認為那個最短的信息才是原始的。


思路

這題就是一個純暴力,但我用了KMP來暴力

這題的題目很難讀懂

這題正解是用KMP中的next數組直接一次出解

俗話說:帶break的暴力都是正解


#include <stdio.h>
#include <string>
#include <cstring>
#include <iostream>
using namespace std;
char a[30], s[1000005], b[30];
int p[1000005];
int main()
{    
    scanf("%s", a);
    for (int i = 0; i < 26
; i++) { b[a[i] - a] = char(i + a); } scanf("%s", s); int len = strlen(s); int j = -1; for (int i = 1; i < (len + 1) / 2; i++) { if (s[i] != s[j + 1] && j != -1) j = p[j]; if (s[i] == s[j + 1]) j++; p[i] = j; } for (int
i = 0; i < (len + 1) / 2; i++) { cout << s[i]; } for (int i = (len + 1) / 2; i <= len; i++) { int jj = -1; int fl = 0; for (int ii = i; ii < len; ii++) { if (a[s[ii] - a] != s[jj + 1] && jj != 0) { break; jj = p[jj]; } if (a[s[ii] - a] == s[jj + 1]) jj++; if (jj == len - i - 1) { fl = 1; break; } } if (fl || i == len) { for (int ii = 0; ii < i; ii++) { cout << b[s[ii] - a]; } break; } cout << s[i]; if (s[i] != s[j + 1] && j != -1) j = p[j]; if (s[i] == s[j + 1]) j++; p[i] = j; } }

jzoj 2937_監聽還原_KMP