码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 4300 (扩展KMP或KMP)

时间:2015-07-16 23:55:04      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:

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

题意:说实话,看半天题目,愣是没看懂,百度题意才看懂,大概意思就是:第一个串串为匹配串,第i个代表字母顺序中的第i个,比如第一个是q,那么,q就代表a。

 第二个串是密文+明文,密文全部都有,但明文可能不全,输出完整的密文+明文。

题解:有两种做法,第一种,用扩展KMP:

          1.先把s2砍半,前面一半必定为密文,后面一半可能是密文+明文。

          2.把前面的一半转化成明文。

          3.用后面的和前面的找最长公共前缀,这个前缀必须到底,换句话说,找到的前缀必须到后一半的最后一个字符。

   第二种,KMP:前面两部分一样,后面只是去找后缀匹配。

 

代码如下:

EXKMP:

技术分享
  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std; 
  6 const int maxn=100010;   //字符串长度最大值
  7 /*next数组的作用:使得在求ex数组的时候成为线性的求法*/
  8 /*ex数组的作用:表示从i。。n的子串与匹配串的最长公共前缀*/
  9 char s1[30],s[30];
 10 char t[maxn];
 11 //ex数组即为extend数组
 12 //预处理计算next数组
 13 int Next[maxn],extand[maxn];  
 14 char S[maxn],T[maxn];  
 15 void GetNext(const char *T){  
 16      int len=strlen(T),a=0;  
 17      Next[0]=len;  
 18      while(a<len-1 && T[a]==T[a+1]) a++;  
 19      Next[1]=a;  
 20      a=1;  
 21      for(int k=2;k<len;k++){  
 22          int p=a+Next[a]-1,L=Next[k-a];  
 23          if( (k-1)+L >= p){  
 24              int j = (p-k+1)>0 ? (p-k+1) : 0;  
 25              while(k+j<len && T[k+j]==T[j]) j++;  
 26              Next[k]=j;  
 27              a=k;   
 28          }   
 29          else  
 30              Next[k]=L;   
 31      }   
 32 }   
 33 void GetExtand(const char *S,const char *T){  
 34      GetNext(T);  
 35      int slen=strlen(S),tlen=strlen(T),a=0;   
 36      int MinLen = slen < tlen ? slen : tlen;  
 37      while(a<MinLen && S[a]==T[a]) a++;  
 38      extand[0]=a;  
 39      a=0;  
 40      for(int k=1;k<slen;k++){  
 41          int p=a+extand[a]-1, L=Next[k-a];  
 42          if( (k-1)+L >= p){  
 43              int j= (p-k+1) > 0 ? (p-k+1) : 0;  
 44              while(k+j<slen && j<tlen && S[k+j]==T[j]) j++;  
 45              extand[k]=j;  
 46              a=k;   
 47          }  
 48          else   
 49              extand[k]=L;   
 50      }   
 51 }   
 52 
 53 int main()
 54 {
 55     int test;
 56     cin>>test;
 57     while(test--)
 58     {
 59         memset(S,0,sizeof(S));
 60         memset(T,0,sizeof(T));
 61         memset(s,0,sizeof(s));
 62         scanf("%s%s",s1,t);
 63         for(int i=0;i<26;i++)
 64         {
 65             s[s1[i]-a]=i+a;
 66         }
 67         //cout<<s<<endl; 
 68         int len = strlen(t);
 69         int mid;
 70         if(len%2)
 71             mid = len/2+1;
 72         else
 73             mid = len/2;
 74         strcpy(S,t+mid);
 75         for(int i=0;i<len;i++)
 76             T[i]=s[t[i]-a];
 77     //    cout<<S<<endl<<T<<endl;
 78         GetExtand(S,T);
 79         int llen = strlen(S);
 80         int lllen= strlen(T);
 81         int temp;
 82         int mm=-1;
 83         for(int i=0;i<llen;i++)
 84         {    //printf("%d ",extand[i]);
 85             if(i+extand[i]+mid==lllen)
 86                 {
 87                     mm=extand[i];
 88                     break;
 89                 }
 90         }
 91     //    cout<<mm<<endl<<temp<<endl<<mid<<endl;
 92         int mmm=len/2;
 93         cout<<t;
 94         if(mm==-1)
 95         mm=0;
 96         for(int i=mm;i<lllen-mm;i++)
 97         {
 98             printf("%c",T[i]);
 99         }
100         cout<<endl;
101     }
102 }
View Code

 

KMP:

技术分享
 1 #include<iostream>
 2 #include<string.h>
 3 using namespace std;
 4 char t[100006],s[100006],str1[26];
 5 int next[100006],str[1000];
 6 void getnext()
 7 {
 8     int i=0,j=-1;
 9     next[0]=-1;
10     int len=strlen(s);
11     while(i<len)
12     {
13         if(j==-1||s[i]==s[j])
14         {
15             i++;
16             j++;
17             next[i]=j;
18         }
19         else
20             j=next[j];
21     }
22 }
23 int kmp()
24 {
25     int i,j=0;
26     int lent=strlen(t);
27     int lens=strlen(s);
28     if(lent%2==1)
29         i=lent/2+1;
30     else
31         i=lent/2;
32     while(i<lent&&j<lens)
33     {
34         if(j==-1||t[i]==s[j])
35         {
36             i++;
37             j++;
38         }
39         else
40             j=next[j];
41     }
42     return j;
43 }
44 int main()
45 {
46     int text;
47     scanf("%d",&text);
48     while(text--)
49     {
50         char ch;
51         int i;
52         scanf("%s",str1);
53         for(i=0;i<26;i++)
54         {
55             ch=str1[i];
56             str[ch]=i;
57         }
58         scanf("%s",t);
59         int lent=strlen(t);
60         for(i=0;i<lent;i++)
61         {
62             int temp=str[t[i]];
63             s[i]=temp+a;
64         }
65         getnext();
66         int j=kmp();
67         if(j*2==lent)
68         {
69             printf("%s\n",t);
70         }
71         else
72         {
73             int tmp1=lent-j;
74             printf("%s",t);
75             for(i=j;i<tmp1;i++)
76                 printf("%c",s[i]);
77             printf("\n");
78         }
79     }
80     return 0;
81 }
View Code

 

HDU 4300 (扩展KMP或KMP)

标签:

原文地址:http://www.cnblogs.com/ikids/p/4652595.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!