出的超级好的一道题。至于好在哪里,请思考题目:

题意抽象出来为给定一个字符串r,找出它的一个最短后缀s,使得这个r可以被 s的某前缀+s的某前缀+......+s的某前缀+s本身构造出来。

具体题目描述如下:

“Be subtle! Be subtle! And use your spies for every kind of business. ” 
— Sun Tzu 
“A spy with insufficient ability really sucks” 
— An anonymous general who lost the war 
You, a general, following Sun Tzu’s instruction, make heavy use of spies and agents to gain information secretly in order to win the war (and return home to get married, what a flag you set up). However, the so-called “secret message” brought back by your spy, is in fact encrypted, forcing yourself into making deep study of message encryption employed by your enemy. 
Finally you found how your enemy encrypts message. The original message, namely s, consists of lowercase Latin alphabets. Then the following steps would be taken: 
* Step 1: Let r = s 
* Step 2: Remove r’s suffix (may be empty) whose length is less than length of s and append s to r. More precisely, firstly donate r[1...n], s[1...m], then an integer i is chosen, satisfying i ≤ n, n - i < m, and we make our new r = r[1...i] + s[1...m]. This step might be taken for several times or not be taken at all. 
What your spy brought back is the encrypted message r, you should solve for the minimal possible length of s (which is enough for your tactical actions).

输入:

There are several test cases. 
For each test case there is a single line containing only one string r (The length of r does not exceed 10 5). You may assume that the input contains no more than 2 × 10 6 characters. 
Input is terminated by EOF.

输出:

For each test case, output one line “Case X: Y” where X is the test case number (starting from 1) and Y is the desired answer.

样例:

abc
aab
abcadabcabcad
aaabbbaaaabbbaa
abcababcd

样例答案:
Case 1: 3
Case 2: 2
Case 3: 5
Case 4: 6
Case 5: 4

题解:这题初看很容易只能想到枚举答案长度i,从r后面截长度为i的后缀然后暴力匹配是否满足条件。复杂度显然太高无法接受。之后如果运用动态规划的思想,可以对r[1...k]考虑子问题。但是会发现由于要加一个s本身,考虑完全同质的子问题有点问题。于是考虑r[1...k]可以表示为s1某前缀+s1某前缀+...+s1某前缀时s1的最短长度那么对于r[1...k+1],如果r[k+1]可以成为s1的某前缀的一部分或者自己成为s1的前缀。s1就仍然满足r[1....k+1]的要求,最短长度不变;如果不可以,那么理论上把s1的末尾添加字符r[k+1]便满足了r[1...k+1]的要求。但是这时得考虑下最后得有一个s本身的问题。所以添加字符的时候不能只加r[k+1],应该加一段字符。从r[1...k+1]中上一次模板串跟r[1..k+1]的一部分完全匹配的地方开始加,加到r[k+1]。一直扫描完题意给的整个r。最后再给一直维护的模板串加一段:最后一次完全匹配的地方到r的末尾的字符。以上是思考过程。

以下是更加严谨的题解叙述:从头开始扫描r,始终维护一个模板串s和上一次完全匹配位置的标记mark:在r[i]处有三种操作:1.若在r[i]处成功进行kmp匹配,则模板串不变2.如匹配失败,动态添加模板串,添加内容为位置为mark至i的子串3.如果进行了一次完全匹配,更新mark。
 1 #include<cstdio>
 2 #include<cstring>
 3 #define rep(i,a,b) for(int i=a;i<=b;++i)
 4 using namespace std;
 5 const int MAXN=110000;
 6 char s[MAXN];
 7 char ans[MAXN];
 8 int next[MAXN];
 9 int tot;
10 int main()
11 {
12     //freopen("in.txt","r",stdin);
13     int cnt=0;
14     while(scanf("%s",s)!=EOF)
15     {
16         int len=strlen(s);
17         tot=0;
18         ans[tot++]=s[0];            //将维护的模板串初始化
19         next[0]=0;
20         int mark=0;                 //mark标记上一次完全匹配的位置
21         for(int i=0,k=0;i<len;++i)
22         {
23             while(k>0&&s[i]!=ans[k])        //尝试s[i]是否能成为维护的模板串前缀的一部分
24             {
25                 k=next[k-1];
26             }
27             if(s[i]==ans[k]) k++;
28             else if(k==0)                   //尝试失败
29             {
30                 for(int j=mark+1;j<=i;++j)  //更新模板串
31                 {
32                     ans[tot++]=s[j];
33                     int tmp=next[tot-2];            //模板串的next数组需要跟着动态更新
34                     while(tmp>0&&ans[tmp]!=ans[tot-1]) tmp=next[tmp-1];
35                     if(ans[tmp]==ans[tot-1]) tmp++;
36                     next[tot-1]=tmp;
37                 }
38                 mark=i;
39             }
40             if(k==tot) mark=i,k=next[tot-1];        //进行了一次完全匹配,更新mark,并将k跳回
41         }
42         for(int j=mark+1;j<len;++j) ans[tot++]=s[j];
43         printf("Case %d: %d\n",++cnt,tot);
44     }
45     return 0;
46 }

做出来之后发现这道题考察到了kmp算法的所有操作。但是需要人将其kmp算法的各个操作有机地拆开与重组,来解决这个新的问题。非常有助于加深对kmp的理解。

转载于:https://www.cnblogs.com/zhixingr/p/7630181.html

hdu 4468 spy 极其精彩的一道kmp灵活运用题相关推荐

  1. 关于《关于一道C#上机题的一点想法》

    看了<关于一道C#上机题的一点想法>和<泛型委托>两篇文章,深有感触,还是关于下面这道题: 题目:17个人围成一圈,从第一个人开始报数,报到3的退出,一直到剩下最后一个人,用面 ...

  2. poj-2406(kmp水题)

    题意:定义一个a*b=字符串a连接字符串b:给你一个字符串s,问你这个字符串最多能用多少个字符串t连接得到:例如:aaaa=4个a构成: 解题思路:kmp水题,next数组除了查找字串以外最广泛的一种 ...

  3. POJ 3167 Cow Pattern ★(KMP好题)

    题意 给你一个数字序列S,再给一个数字序列pattern,S和pattern中的数字都是1到s(s<=25).每个序列里的数字都有个排名,也就是第几小,现在我们要用pattern来匹配S.在本题 ...

  4. 关于欧拉工程的一道递推题

    今天来讲的是在欧拉工程上的一道递推题,题目描述如下链接. 题目:https://projecteuler.net/problem=492 当然,这道题在51Nod上有一个比较通用的版本,链接如下 题目 ...

  5. c语言成绩等级switch语句,请高手 帮忙做一道c语言题 编程,把百分制成绩转换成5级记分制,要求用switch语句。 90分以上(包括90):...

    请高手 帮忙做一道c语言题 编程,把百分制成绩转换成5级记分制,要求用switch语句. 90分以上(包括90): 关注:243  答案:6  mip版 解决时间 2021-02-04 20:52 提 ...

  6. 一道经典极限题的分析与求解

    一道经典极限题的分析与求解 题目 lim⁡x→∞ex(1+1x)x2\lim_{x\to \infty}\frac{\mathrm{e}^x}{(1+\frac1x)^{x^2}} x→∞lim​(1 ...

  7. java语言编程三角形图形_编程题:编写程序输入三角形的3条边长,计算并输出... 求助一道JAVA编程题:编写一个类似记事本的图形用......

    导航:网站首页 > 编程题:编写程序输入三角形的3条边长,计算并输出... 求助一道JAVA编程题:编写一个类似记事本的图形用... 编程题:编写程序输入三角形的3条边长,计算并输出... 求助 ...

  8. YTU 3837问题 E: 一道老卢题

    题目描述 如题,这是一道老卢题.请输出 nnn 以内有多少个平方数.我们定义平方数为该数是一个数的平方. 输入 第一行输入 ttt,表示有多少组,后 ttt 行每行一个数 nnn. 输出 每一行输出 ...

  9. 每天一道大厂SQL题【Day01】

    每天一道大厂SQL题[Day01] 大家好,我是Maynor.相信大家和我一样,都有一个大厂梦,作为一名资深大数据选手,深知SQL重要性,接下来我准备用100天时间,基于大数据岗面试中的经典题,以每日 ...

最新文章

  1. memcache安装
  2. SSH异常“Failed to start OpenSSH Server daemon”问题排查
  3. 4天快速入门python数据挖掘_4天快速入门Python数据挖掘
  4. Linux常用命令-入门
  5. PMCAFF | 史上最完整的沙龙活动策划总结
  6. 富交互Web应用中的撤销和前进
  7. Ubuntu 9.04下安装source navigator---linux下看代码工具
  8. MFC Edit控件 error:“DDX_Control”: 不能将参数 3 从“int”转换为“CWnd ”
  9. 使用执行程序和ThreadPoolExecutor的Java线程池示例
  10. MySQL架构与历史【v1】【励志把高性能MySQL吃掉】
  11. mysql 查看锁表_MySQL的四种事务隔离级别
  12. 从机器学习到深度学习
  13. arduinouno的地是相连的吗_垫圈锁紧,靠谱吗?
  14. 滴滴开源 ​DoraemonKit:一款像哆啦A梦般全能的App研发工具
  15. 十五个问题了解个税汇算清缴
  16. 正确与错误、真理与谬误
  17. Bert代码详解及模型介绍
  18. PMM 监控原理以及部署
  19. Effective C++条款09:绝不在构造和析构过程中调用virtual函数
  20. 认证、授权、鉴权和权限控制

热门文章

  1. Nature论文爆出千行Python代码Bug,或影响百篇学术论文
  2. 微软出资10亿美元研究AGI,意与谷歌竞争?
  3. 批评“古风”歌词“狗屁不通”就是不尊重?我们又都成了“垃圾听众”
  4. linux基础知识和命令试题,Linux基础试题及答案
  5. Java---中国有句俗语叫“三天打鱼两天晒网”。某人从2010年1月1日起开始“三天打鱼两天晒网”,问这个人在以后的某一天中是“打鱼”还是“晒网”。
  6. css grid 自动高度_2020年你不应该错过的CSS新特性(二)
  7. 如何保证RabbitMQ消息队列的高可用?
  8. 子空间迭代法 matlab,基于MATLAB的一类迭代分析
  9. python如何统计字典里面健的数量_Python中使用Counter进行字典创建以及key数量统计的方法...
  10. 矩形变弧度角_在上海做下颌角整形这些医生错过后悔都来不及,案例分享