HDU 4300 (扩展KMP或KMP)

题目链接: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 }

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 }

时间: 2024-08-24 11:51:03

HDU 4300 (扩展KMP或KMP)的相关文章

hdu 4300 Clairewd’s message (KMP)

给定一个翻译表,即第i个字母用哪个字母表示 再给一个串,里面前面为密文,后面为明文,密文一定是完整的,但明文不完整或可能没有 求这个完整的前面密文后面明文的串 # include <stdio.h> # include <algorithm> # include <string.h> using namespace std; int len; int next[100010]; char a1[100010],a2[100010],a3[100010]; void Ge

HDU 4300 Clairewd&#39;s message ( 拓展KMP )

题意 : 给你一个包含26个小写字母的明文密文转换信息字符串str,第一个表示'a'对应的密文是str[0].'b'对应str[1]--以此类推.接下来一行给你一个另一个字符串,这个字符串由密文+明文组成,但是现在后面部分的明问可能有不完整的情况(也有可能缺失只包含密文),问你现在最少需要补充多多少个字符串才能使得字符串变成完整的满足==>密文+密文对应的明文 组成的字符串,将这个完整的字符串输出出来. 分析 : 冷静分析一下可以发现,在给出的残缺字符串中,前面的一半肯定是属于密文的!如果不是这

HDU 4300 Clairewd‘s message 拓展KMP入门

HDU 4300 Clairewd's message 拓展KMP入门 题意 原题链接 这个题关键是要读懂题意,我做的时候就没有读懂,泪.题意是说给你的一个两个字符串,一个是26个字母密码表,依次对应替换的字母.然后给你一个字符串,这个字符串是不完整的(完整的应该是前半部分是加密的,后半部分是解密了的),然而,给你的字符串一定是加密的部分+一部分解密的部分(可以是全部,也可以是没有),让你求出最短的完整字符串,包括密文和明文: 解题思路 考虑给出的字符串S加密部分一定全部给出,所以给出的字符串的

HDU 2594 Simpsons’ Hidden Talents KMP题解

KMP的应用.直接使用s1产生next 数组,然后在s2中搜索s1,那么记录最后一个搜索到的数值,就是s1的前缀在s2中的最长后缀了. 本题应该不能直接调用strstr了吧. #include <stdio.h> #include <vector> #include <string.h> #include <algorithm> #include <iostream> #include <string> #include <li

hdu 3374 String Problem (kmp+最大最小表示法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3374 题目大意:输出最大和最小的是从哪一位开始的,同时输出最小循环节的个数. 这里简单介绍对字符串最小表示的方法: (1)  利用两个指针p1, p2.初始化时p1指向s[0], p2指向s[1]. (2)  k = 0开始,检验s[p1+k] 与 s[p2+k] 对应的字符是否相等,如果相等则k++,一直下去,直到找到第一个不同,(若k试了一个字符串的长度也没找到不同,则那个位置就是最小表示位置,

HDU 2087 剪花布条 KMP题解

KMP的应用,不过查找的时候注意一点就够了:查找到一个子串的时候,直接跳过整个串,而不是使用next数组前跳,因为根据题意需要剪出小饰条,小饰条之间不能重叠. const int MAX_N = 1001; char txt[MAX_N], pat[MAX_N]; int next[MAX_N], len; void genNext() { for (int i = 1, j = 0; i < len; ) { if (pat[i] == pat[j]) next[i++] = ++j; els

KMP算法 KMP模式匹配 二(串)

B - KMP模式匹配 二(串) Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:131072KB     64bit IO Format:%lld & %llu Description 输入一个主串和一个子串,用KMP进行匹配,问进行几趟匹配才成功,若没成功,则输出0 Input 输入一个主串和一个子串 Output 匹配的趟数 Sample Input ababcabcacbab abcac

KMP算法 KMP模式匹配 一(串)

A - KMP模式匹配 一(串) Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:131072KB     64bit IO Format:%lld & %llu Description 求子串的next值,用next数组存放,全部输出 Input 输入一个字符串 Output 输出所有next值 Sample Input abaabcac Sample Output 0 1 1 2 2 3 1

hdu 4300 Clairewd’s message(详解,扩展KMP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4300 Problem Description Clairewd is a member of FBI. After several years concealing in BUPT, she intercepted some important messages and she was preparing for sending it to ykwd. They had agreed that ea