HDU - 4300 Clairewd’s message (字符串Hash)

题解

给定两个字符串,第一个字符串为字符串的转换规则,(如第二个例子,当第二个字符串中出现q字符后,就要把它变为a字符,即q对应a,w对应b)。

第二个字符串,前一部分为密文,就是需要你按照转换规则,转换的字符串,后一部分为原文。但是原文的长度不知道,也可能原文给的不全,但是密文是完整的。需要你补全第二个字符串。求出最短的字符串。

易知如果存在密文和明文对应,密文长度一定大于等于明文长度,并且密文长度越长,对应密文+明文(即最后结果)越长。故贪心的想,我们希望找一个尽量短的密文。
做法如下。首先预处理,将密文和明文的混合文分别转换为全密文和全明文。再将从混合文和全密文Hash。从中间开始枚举位置,判断混合文的前缀和全密文的后缀hash值是否相等,若相等则当前位置为混合文的密文与明文的分界线。

代码

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int nmax = 1e5  + 100;
const int INF = 0x3f3f3f3f;
const ull p = 67;
int t,len;
char mmp[26]; char code[26];
char str[nmax], trans[nmax], ori[nmax];
ull hashstr[nmax], hashtrans[nmax], pp[nmax] = {0,p};
inline ull strsub(int l, int r){
    return hashstr[r] - hashstr[l-1] * pp[r - l + 1];
}
inline ull transsub(int l, int r){
    return hashtrans[r] - hashtrans[l-1] * pp[r - l + 1];
}
int main() {
    for(int i = 2;i<nmax;++i) pp[i] = pp[i-1] * p;
    scanf("%d",&t);
    while(t--){
        memset(str,0,sizeof str); memset(trans,0,sizeof trans);memset(ori,0,sizeof ori);
        scanf("%s",mmp); scanf("%s",str+1);
        for(int i = 0;i<26;++i){int pos = mmp[i] - 'a'; code[pos] = i;}
        len = strlen(str+1);
        for(int i = 1;i<=len;++i) trans[i] = mmp[str[i] - 'a'];
        for(int i = 1;i<=len;++i) ori[i] = code[str[i] - 'a'] + 'a';
        hashstr[1] = str[1], hashtrans[1] = trans[1];
        for(int i = 2;i<=len;++i)
            hashstr[i] = hashstr[i-1] * p + str[i],
            hashtrans[i] = hashtrans[i-1] * p + trans[i];
        int pos = (len+1) / 2;
        bool isfind = false;
        for(int i = pos+1;i<=len;++i){
            int lens = len - i + 1;
            ull tarfront = strsub(1,lens);
            ull tarback = transsub(i,len);
            if(tarfront == tarback){
                for(int j = 1;j<i;++j) printf("%c",str[j]);
                for(int j = 1;j<i;++j) printf("%c",ori[j]);
                isfind = true; printf("\n");
                break;
            }
        }
        if(isfind){ // do nothing
        }else printf("%s%s\n",str+1,ori+1);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/pengwill97/article/details/80888336