HDU 4300 Clairewd’s message

Description:

Clairewd is a member of FBI. After several years concealing in BUPT, she intercepted some important messages and she was preparing for sending it to ykwd. They had agreed that each letter of these messages would be transfered to another one according to a conversion table. 
Unfortunately, GFW(someone's name, not what you just think about) has detected their action. He also got their conversion table by some unknown methods before. Clairewd was so clever and vigilant that when she realized that somebody was monitoring their action, she just stopped transmitting messages. 
But GFW knows that Clairewd would always firstly send the ciphertext and then plaintext(Note that they won't overlap each other). But he doesn't know how to separate the text because he has no idea about the whole message. However, he thinks that recovering the shortest possible text is not a hard task for you. 
Now GFW will give you the intercepted text and the conversion table. You should help him work out this problem. 

Input:

The first line contains only one integer T, which is the number of test cases. 
Each test case contains two lines. The first line of each test case is the conversion table S. S[i] is the ith latin letter's cryptographic letter. The second line is the intercepted text which has n letters that you should recover. It is possible that the text is complete.

Hint:
Range of test data: 
T<= 100 ; 
n<= 100000; 

Output:

For each test case, output one line contains the shorest possible complete text. 

Sample Input:

2 abcdefghijklmnopqrstuvwxyz
abcdab
qwertyuiopasdfghjklzxcvbnm
qwertabcde

Sample Output:

abcdabcd
qwertabcde

Hint:

Range of test data: 
        
T<= 100 ;
n<= 100000;
题意:在传输机密文件(字母组成)时,每个字母都需要转化为其他字母来进行加密,在传输过程中先传输全部的密文,再传输明文,为了防止机密落入坏人之手在传输到一部分时不继续传输了(有可能传输完啦,有可能没有),现在给出翻译的模板和传输的字符串,要求出这个文件可能的最小完整文件(密文明文都有才叫完整)。
#include<stdio.h>
#include<string.h>

const int N=1e6+10;

char a[N], b[N], c[N]; ///a是翻译模板,b是传输的字符串(被截取的),c是可能是明文的字符串
int Next[N], lb, lc;

void Getnext() ///这个Next数组存放的是将截获的字符串按照翻译模板复原的Next值
{
    int i = 0, j = -1;

    Next[0] = -1;

    while (i < lb)
    {
        if (j == -1 || b[i] == b[j])
        {
            i++;
            j++;

            Next[i] = j;
        }
        else j = Next[j];
    }
}

int KMP()
{
    int i = 0, j = 0;

    while (i < lc && j < lb)
    {
        if (j == -1 || c[i] == b[j])
        {
            i++;
            j++;

            if (i == lc) ///找到恢复后的字符串b在可能是明文中存在部分的最后一个的下标(这部分肯定是明文)
                return j;
        }
        else j = Next[j];
    }
    
    return 0;
}

int main ()
{
    int T, i, j, k;

    scanf("%d", &T);

    while (T--)
    {
        scanf("%s", a);
        scanf("%s", b);

        lb = strlen(b);
        lc = lb / 2;

        printf("%s", b); ///此时的字符串b还没有被恢复,那么我们直接先输出好啦,反正我们只是需要添加,前面的还是需要保存的

        strcpy(c, b+(lb+1)/2); ///首先如果字符串b是一个完整的机密文件(密文明文都完整),那么密文和明文肯定各占一半,那么我们就把后一半当做明文
                               ///lb+1的原因是最开始的明文肯定是<=密文的
        for (i = 0; b[i] != '\0'; i++)
        {
            for (j = 0; a[j] != '\0'; j++)
            {
                if (b[i] == a[j])
                {
                    b[i] = 'a' + j; ///恢复字符串,那么本来是密文在前,明文在后,现在变成了明文在前,密文在后
                    break;
                }
            }
        }

        Getnext();

        k = KMP(); 

        for (i = k; i < lb-k; i++) ///既然前k个已经确定是明文啦,那么现在肯定已经存在k个密文啦(一一对应的嘛),之前也说啦现在字符串b已经变成明文在前,密文在后啦,那么后面肯定有k个密文,是不能被输出的,我们添加的只可能是明文
            printf("%c", b[i]); 
        printf("\n");
    }

    return 0;
}
posted @ 2015-10-09 14:07  搁浅の记忆  阅读(128)  评论(0编辑  收藏  举报