hdu 4300 Clairewd’s message

简介: 点击打开链接hdu 4300 思路:kmp+next数组的应用 分析: 1 题目要求的是给定一个不完整的由n个字符构成的字符串并且字符串有密文和明文两部分组成,现在要求完整的字符串。

点击打开链接hdu 4300


思路:kmp+next数组的应用

分析:
1 题目要求的是给定一个不完整的由n个字符构成的字符串并且字符串有密文和明文两部分组成,现在要求完整的字符串。
2 很明显密文的长度不确定,现在又要求最短的字符串长度。由于在完整的字符串中密文和明文的长度是一样的,那么输入的字符串中至少有(n+1)/2是密文,所以我们假设密文后面的都是明文,那么我们将这些明文转化为密文后求next数组就可以知道前缀和后缀的最大的匹配数,那么如果匹配数越大就说明总的串的长度就越小。
3 但是有个地方需要注意,输入的字符串长度为n,那么至少(n+1)/2为密文,那么明文最多为tmp = n-(n+1)/2,所以next[n]的最大值是不能超过tmp的,如果超过了那么就另next[len] = tmp即可,说明已经最大了。

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

#define MAXN 100010
#define N 30

int t;
int next[MAXN];
char mp[N];
char pattern[MAXN];

/**求最大的匹配数*/
void getNext(){
    int len = strlen(pattern);
    next[0] = next[1] = 0;
    for(int i = 1 ; i < len ; i++){
       int j = next[i];
       while(j && pattern[i] != pattern[j])
          j = next[j];
       next[i+1] = pattern[i] == pattern[j] ? j+1 : 0;
    }
}

int main(){
  char str[MAXN];
  scanf("%d" , &t);
  while(t--){
     scanf("%s" , mp);
     scanf("%s" , pattern);
  
     int len = strlen(pattern);
     
     /*求最大的匹配数*/
     memcpy(str , pattern , sizeof(pattern));
     for(int i = (len+1)/2 ; i < len ; i++){
        int num = pattern[i]-'a';
        pattern[i] = mp[num];
     }

     getNext();
     
     /*当最大匹配数超过(len-(len+1)/2)的是就要直接把next[len] = len-(len+1)/2*/
     if(next[len] > (len-(len+1)/2))
       next[len] = len-(len+1)/2;
     
     int num = len-next[len];
     printf("%s" , str);
     /*输出剩下的明文*/
     int j = num-next[len];
     int i = num-j;
     /*把密文转化为明文*/
     for(; i < num ; i++){
         for(int j = 0 ; j < 26 ; j++){
             if(str[i] == mp[j]){
               printf("%c" , j+'a');
               break;
            }
         }         
     }
     printf("\n");
  }
  return 0;
}

利用kmp的扩展

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

#define MAXN 100010
#define N 30

int t;
int next[MAXN];
int extend[MAXN];
char mp[N];
char text[MAXN];
char pattern[MAXN];

/*求扩展kmp的next*/
void getNext(){
   int len = strlen(pattern);
   int a = 0;

   next[0] = len;
   while(a < len-1 && pattern[a] == pattern[a+1])
       a++;
   next[1] = a;
   a = 1;/*a重新赋值为1*/

   for(int k = 2 ; k < len ; k++){
      int p = a+next[a]-1;
      int l = next[k-a];
      if(k+l-1 >= p){
        int j = max(p-k+1 , 0);
        while(k+j < len && pattern[k+j] == pattern[j])
             j++;
        next[k] = j;
        a = k;
      }
      else 
        next[k] = l;
   }
}

/*求estend数组*/
void getExtend(){
    int n = strlen(text);
    int m = strlen(pattern);
    int a = 0;
    int minLen = min(n , m);

    while(a < minLen && text[a] == pattern[a])
         a++;
    extend[0] = a;
    a = 0;

    for(int k = 1 ; k < n ; k++){
       int p = a+extend[a]-1;
       int l = next[k-a];
       if(k-1+l >= p){
         int j = max((p-k+1) , 0);
         while(k+j < n && j < m && text[k+j] == pattern[j])
              j++;
         extend[k] = j;
         a = k;
       }
       else
         extend[k] = l;
    }
}

int main(){
   char str[MAXN];
   int max;
   scanf("%d" , &t);
   while(t--){
      scanf("%s" , mp);
      scanf("%s" , pattern);

      int len = strlen(pattern);
      memcpy(str , pattern , sizeof(pattern));
      
      /*求出模式串*/
      int pos = 0;
      memset(text , '\0' , sizeof(text));
      for(int i = (len+1)/2 ; i < len ; i++){
         int num = pattern[i]-'a';
         text[pos++] = mp[num];
      }
      pattern[(len+1)/2] = '\0';

      /*求next数组*/
      getNext();
      
      /*求extend数组*/
      getExtend();
      
      /*求最长的公共前缀数*/
      int max = 0;
      for(int i = 0 ; i < pos ; i++){
         if(max < extend[i] && extend[i]+i == pos)
            max = extend[i];
      }
      
      /*输出*/
      printf("%s" , str);
      int cir = len-max;/*求出密文的长度*/
      int j = cir-max;
      int i = cir-j;/*求出要输出的起始位置*/
      for(; i < cir ; i++){
         for(int j = 0 ; j < 26 ; j++){
            if(str[i] == mp[j]){
              printf("%c" , j+'a');
              break;
            }
         }
      }
      printf("\n");
   }
   return 0;
}



目录
相关文章
|
11月前
|
存储 自然语言处理 关系型数据库
基于阿里云通义千问开发智能客服与问答系统
在企业的数字化转型过程中,智能客服系统已成为提高客户满意度和降低运营成本的重要手段。阿里云的通义千问作为一款强大的大语言模型,具有自然语言理解、对话生成、知识检索等能力,非常适合用来开发智能客服与问答系统。 通过本博客,我们将演示如何基于阿里云的通义千问模型,结合阿里云相关产品如函数计算(FC)、API网关、RDS等,搭建一个功能齐全的智能客服系统。
1370 5
|
算法 编译器 C++
【C++ 泛型编程 中级篇】C++ 编译时技术:探索 if constexpr 和 std::enable_if
【C++ 泛型编程 中级篇】C++ 编译时技术:探索 if constexpr 和 std::enable_if
286 0
|
JSON C语言 数据格式
使用cJSON库实现JSON与C结构体的互转
在实际应用中,我们经常需要将JSON格式的数据与C语言中的结构体进行相互转换。cJSON是一个非常便捷的C语言JSON解析库,它可以帮助我们在C语言中轻松地处理JSON数据。本文将介绍如何使用cJSON库来实现JSON数据与C结构体的互转。
1202 2
|
设计模式 算法 Java
内卷严重~面试八股文层出不穷!唯2023版Java复盘手册有复盘之路
最近有不少小伙伴表示内卷实在是太严重了,不少程序员都有辞退失业或跳槽的想法,今天给大家分享的这份手册可以快速帮大家找到正确思路,无论你是失业还是跳槽都推荐你看一看,这份手册涵盖了市面上90%的Java面试内容,十分全面! 不到最后一刻千万不要放弃,也不要灰心,哪怕到十一月还没有拿到offer也没关系,殊不知等到年底补录的时候也是一个非常容易进大厂拿offer的机会。
|
JSON JavaScript 前端开发
【重温基础】11.Map和Set对象
【重温基础】11.Map和Set对象
242 0
有效解决办法:marven:Fatal error compiling: 无效的目标发行版: 11
有效解决办法:marven:Fatal error compiling: 无效的目标发行版: 11
1255 0
No package ‘glib-2.0‘ found/No package ‘gobject-2.0‘ found
No package ‘glib-2.0‘ found/No package ‘gobject-2.0‘ found
621 0
|
程序员
技术大牛面试阿里程序员挂在第四轮,看看他怎么总结
众所周知阿里巴巴作为互联网公司巨头之一,面试流程是复杂且竞争激烈,HR在面试中的权力非常大,你能不能过基本就靠HR一句话,很多几轮技术面试上都过了却卡在了HR这里。 不过在小编印象里HR看人是非常准的,记得我早年毕业去找工作时,几十个人一同面试,最后只录取了四五个人,我侥幸在里面,那HR说了一段话我至今都印象深刻:你们如果没做自我介绍没有说话,那你们在我眼里只有性别上的区分而已,你们做了自我介绍,回答了我几个问题,我基本能看出你大概是怎样的一个人,符不符合我们公司的要求,我也非常相信自己的眼光,因为这是我经过面试无数人锻炼出的技能。
|
Java 应用服务中间件 Linux
Centos7 Tomcat9随机启动
环境: Centos7、JDK 1.8、Tomcat9 安装好JDK跟Tomcat后在/usr/lib/systemd/system/目录下新建文件tomcat.service,内容如下,对应的位置替换一下 [Unit] Description=Tomcat9 After=syslog.
1397 0
|
移动开发 调度 Python