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 }
View Code

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4300

posted on 2015-02-02 23:44  xiao_xin  阅读(94)  评论(0编辑  收藏  举报

导航