HDU 4300 -- 扩展KMP

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4300
题目大意:第一个字符串A是密码表,为a~z所对应的新字母,第二个字符串B是密码+(部分)原文构成的字符串,现在让你补全这个字符串,使得这个字符串前半部分是密码,后半部分是原文
思路: 先将串B全部看成是密码,然后利用密码表将其转换成一个新串C,所以,原文就出现在了串B的后缀,和串C的前缀这两个地方。利用扩展Kmp中的extend数组,求出B的后缀与串C的最长公共前缀即可
AC代码:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5+5;
char s[28], str[maxn], c[maxn];
int kmp_next[maxn], extend[maxn];
map<char, char> pp;

void pre_kmp(char x[], int m, int kmp_next[])
{
    kmp_next[0] = m;
    int j = 0, k = 1;
    while(j+1 < m && x[j] == x[j+1])    j++;
    kmp_next[1] = j;
    for(int i = 2; i < m; i++){
        int p = kmp_next[k] + k -1;
        int l = kmp_next[i-k];
        if(i+l < p + 1) kmp_next[i] = l;
        else{
            j = max(0, p-i+1);
            while(i + j < m && x[i+j] == x[j])  j++;
            kmp_next[i] = j;
            k = i;
        }
    }
}

void exkmp(char x[], int m, char y[], int n, int kmp_next[], int extend[])
{
    pre_kmp(x, m, kmp_next);
    int j = 0;
    while(j < n && j < m && x[j] == y[j])   j++;
    extend[0] = j;
    int k = 0;
    for(int i = 1; i < n; i++){
        int p = extend[k] + k -1;
        int l = kmp_next[i-k];
        if(i+l < p+1)   extend[i] = l;
        else{
            j = max(0, p-i+1);
            while(i+j < n && y[i+j] == x[j] && j < m)   j++;
            extend[i] = j;
            k = i;
        }
    }
}

int main()
{
    int T;
    cin >> T;
    while(T--){
        cin >> s >> str;
        int len = strlen(str);
        int len2 = strlen(s);
        for(int i = 0 ; i < len2; i++){
            pp[s[i]] = 'a'+i;
        }
        for(int i = 0; i < len; i++){
            c[i] = pp[str[i]];
        }
        c[len] = 0;
        exkmp(c, len, str, len, kmp_next, extend);
        int k;
        for(k = 0; k < len; k++){
            if(k + extend[k] >= len && k >= extend[k])  break;
        }
        for(int i = 0; i < k; i++)  printf("%c", str[i]);
        for(int i = 0; i < k; i++)  printf("%c", pp[str[i]]);
        cout << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/water_zero_saber/article/details/81186497