HDU-4300-Clairewd’s message(KMP+特判)
阿新 • • 發佈:2019-02-04
博主連結
題目
題意:
先給你一個密碼錶。然後給你一個不一定完整的串。原串滿足前一半是密碼,後一半是明碼。要求你最小的補全這個串。
題解:
設給的串長度為len,則1…(len+1)/2的字母一定是密碼。我們將1…(len+1)/2的字母全部安裝密碼錶轉換成原文,然後將得到的串求Next陣列。再根據Next陣列求出最大的相等的前後綴(長度一定小於或等於len/2,題目要求),然後輸出就可以。然後這裡一定要先加一個特判是不是不存在相等的前後綴,也就是s[1]!=s[len],這時輸出原串一次,再輸出一次原串全解密的串.
程式碼:
#include<stdio.h> #include<bits/stdc++.h> #define met(a) memset(a,0,sizeof(a)) #define fup(i,a,n,b) for(int i=a;i<n;i+=b) #define fow(j,a,n,b) for(int j=a;j>0;j-=b) #define MOD(x) (x)%mod using namespace std; const int maxn = 1e6 + 10; const int mod = 1e9 + 7; typedef long long ll; char s[maxn],s1[maxn]; char t[maxn]; char m[33]; int nex[maxn]; void Get_nex() { int j = 0; for (int i = 1; s[i]; i++) { while (s[i] != s[j + 1] && j != 0)j = nex[j]; if (s[i] == s[j + 1] && i != 1)j++; nex[i] = j; } } int main() { int t,n; scanf("%d", &t); while (t--) { scanf("%s", m+1); scanf("%s", s+1); int len = strlen(s+1); for (int i = 1;i<=len+1; i++)s1[i] = s[i]; for (int j = 1; j <= (len +1)/ 2; j++) { //進行原串前半部分解密 for (int i = 1; i <= 26; i++) { if (s[j] == m[i]) { s[j] = 'a' + i-1; break; } } } Get_nex(); int nn =0; int a = nex[len]; if (a == 0) { // 如果不存在相等的前後綴 printf("%s", s1 + 1); for (int j = (len+1)/2+1; j <= len; j++) { for (int i = 1; i <= 26; i++) { if (s[j] == m[i]) { s[j] = 'a' + i - 1; break; } } } printf("%s\n", s+1); continue; } while (a != 0) { //找出最大的相等的前後綴且長度小於或等於len/2 if (s[a] == s[len]) { if (a <= len / 2)nn = max(nn, a); a = nex[a]; } } printf("%s", s1+1); for (int i = nn+1; i <= len -nn; ++i)printf("%c",s[i]); printf("\n"); } }