hdu4300 扩展KMP
题意好难懂==
给定26个是a-z的密文,然后将给定的字符串符合密文+对应明文的最短串输出
注意到前(len+1)/2肯定是密文,然后翻译成明文与后面进行EXKMP
只要extend[i]可以到达末尾即为最小,再加上后面翻译即可
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 char S[100005],T[100005],d[50]; 6 int extend[1000005],next[100005]; 7 void EKMP(char s[],char t[],int lens,int lent) 8 { 9 int i,j,p,l,a; 10 next[0]=lent; j=0; 11 while (j+1<lent&&t[j]==t[j+1]) j++; 12 next[1]=j; 13 a=1; 14 for (i=2;i<lent;i++) 15 { 16 p=next[a]+a-1; 17 l=next[i-a]; 18 if (i+l<p+1) next[i]=l; 19 else{ 20 j=max(0,p-i+1); 21 while (i+j<lent&&t[i+j]==t[j]) j++; 22 next[i]=j; 23 a=i; 24 } 25 } 26 27 j=0; 28 while (j<lens&&j<lent&&s[j]==t[j]) j++; 29 extend[0]=j; a=0; 30 for (i=1;i<lens;i++) 31 { 32 p=extend[a]+a-1; 33 l=next[i-a]; 34 if (l+i<p+1) extend[i]=l; 35 else{ 36 j=max(0,p-i+1); 37 while (i+j<lens&&j<lent&&s[i+j]==t[j]) j++; 38 extend[i]=j; 39 a=i; 40 } 41 } 42 } 43 char s[100005]; 44 int main() 45 { 46 int i,j,Case,len,half; 47 scanf("%d",&Case); 48 while (Case--) 49 { 50 scanf("%s",s); 51 for (i=0;i<26;i++) 52 d[s[i]-'a'+1]='a'+i; 53 scanf("%s",s); 54 len=strlen(s); 55 half=(len+1)/2; 56 for (i=half;i<len;i++) 57 S[i-half]=s[i]; 58 for (i=0;i<half;i++) 59 T[i]=d[s[i]-'a'+1]; 60 EKMP(S,T,len-half,half); 61 for (i=0;half+i<len;i++) 62 if (extend[i]==len-half-i) break; 63 if (i+half>=len){ 64 printf("%s",s); 65 for (j=0;j<len;j++) s[j]=d[s[j]-'a'+1]; 66 printf("%s\n",s); 67 } 68 else{ 69 for (j=0;j<half+i;j++) { 70 printf("%c",s[j]); 71 s[j]=d[s[j]-'a'+1]; 72 } 73 for (j=0;j<half+i;j++) printf("%c",s[j]); 74 printf("\n"); 75 } 76 } 77 return 0; 78 }