HDU4300 Clairewd’s message
雪姐无敌~
这题传说是一个扩展KMP的应用,不过我不会exKMP,只好先用KMP乱搞一下了。
KMP我TMD也不会啊。。。这题就当加深理解了。。
我们将原串称为MIA,将解密后的串称为STR
我们要找到的的是MIA的后辍与STR的前辍的最长的交。
解题的方法就是以MIA为母串,以STR为模式串,做一次KMP匹配。从而求得当母串完全匹配之后,模式串的匹配位置。
如M:abcdab T:abcdab (样例,没有加密)
最后的匹配位置就是ab < ...
所以M的前4个是加密串,后4个可以由前4个解密得到。
但是,有特殊情况是abababa这样的。
匹配位置是len,而题目中给出的信息是M[0...n-1]+S[0...m] (0<=m<len)
所以我们所要的结果就是next[ptr]。
再加上要求最短的信息串,则如果ptr>len/2,则ptr=next[ptr],这样就可以得到最后的结果。
学艺不精,语文不好,说错了不怪我。大家参考着看呗~~
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <algorithm> 5 #include <iostream> 6 #include <vector> 7 #include <string> 8 #include <bitset> 9 10 using namespace std; 11 12 #define print(x) cout<<x<<endl 13 #define input(x) cin>>x 14 15 const int SIZE=100000; 16 17 int next[SIZE+5]; 18 char conv[32],anti[32]; 19 char str[SIZE+5],mia[SIZE+5]; 20 int len; 21 22 void kmp_get_next() 23 { 24 next[0]=-1; 25 for(int i=0,j=-1;i<len;i++,j++,next[i]=j) 26 { 27 while(j>=0 and str[i]!=str[j]) j=next[j]; 28 } 29 } 30 31 char decode(char x) 32 { 33 return conv[x-'a']; 34 } 35 36 void make_anti() 37 { 38 for(int i=0;conv[i];i++) 39 { 40 anti[conv[i]-'a']='a'+i; 41 } 42 } 43 44 char encode(char x) 45 { 46 return anti[x-'a']; 47 } 48 49 int slove() 50 { 51 int i,j; 52 i=j=0; 53 while(i<len and j<len) 54 { 55 if(j==-1 or mia[i]==str[j]) 56 { 57 i++;j++; 58 } 59 else 60 { 61 j=next[j]; 62 } 63 } 64 while(j>len/2) j=next[j]; 65 return j; 66 } 67 68 int main() 69 { 70 int T; 71 input(T); 72 while(T--) 73 { 74 memset(mia,0,sizeof(mia)); 75 memset(str,0,sizeof(str)); 76 memset(next,0,sizeof(next)); 77 scanf("%s",conv); 78 scanf("%s",str); 79 len=strlen(str); 80 for(int i=0;str[i];i++) 81 { 82 mia[i]=decode(str[i]); 83 } 84 make_anti(); 85 kmp_get_next(); 86 int k=slove(); 87 for(int i=0;mia[i+k];i++) 88 { 89 printf("%c",str[i]); 90 } 91 for(int i=0;mia[i+k];i++) 92 { 93 printf("%c",encode(str[i])); 94 } 95 puts(""); 96 } 97 return 0; 98 }