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

题意抽象出来为给定一个字符串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。
 #include<cstdio>
#include<cstring>
#define rep(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const int MAXN=;
char s[MAXN];
char ans[MAXN];
int next[MAXN];
int tot;
int main()
{
//freopen("in.txt","r",stdin);
int cnt=;
while(scanf("%s",s)!=EOF)
{
int len=strlen(s);
tot=;
ans[tot++]=s[]; //将维护的模板串初始化
next[]=;
int mark=; //mark标记上一次完全匹配的位置
for(int i=,k=;i<len;++i)
{
while(k>&&s[i]!=ans[k]) //尝试s[i]是否能成为维护的模板串前缀的一部分
{
k=next[k-];
}
if(s[i]==ans[k]) k++;
else if(k==) //尝试失败
{
for(int j=mark+;j<=i;++j) //更新模板串
{
ans[tot++]=s[j];
int tmp=next[tot-]; //模板串的next数组需要跟着动态更新
while(tmp>&&ans[tmp]!=ans[tot-]) tmp=next[tmp-];
if(ans[tmp]==ans[tot-]) tmp++;
next[tot-]=tmp;
}
mark=i;
}
if(k==tot) mark=i,k=next[tot-]; //进行了一次完全匹配,更新mark,并将k跳回
}
for(int j=mark+;j<len;++j) ans[tot++]=s[j];
printf("Case %d: %d\n",++cnt,tot);
}
return ;
}
做出来之后发现这道题考察到了kmp算法的所有操作。但是需要人将其kmp算法的各个操作有机地拆开与重组,来解决这个新的问题。
非常有助于加深对kmp的理解。

hdu 4468 spy 极其精彩的一道kmp灵活运用题的更多相关文章

  1. HDU 4468 Spy(KMP+贪心)(2012 Asia Chengdu Regional Contest)

    Description “Be subtle! Be subtle! And use your spies for every kind of business. ”― Sun Tzu“A spy w ...

  2. HDU - 4333 :Revolving Digits (扩展KMP经典题,问旋转后有多少个不同的数字小于它本身,等于它本身,大于它本身。)

    One day Silence is interested in revolving the digits of a positive integer. In the revolving operat ...

  3. hdu 1711 Number Sequence(KMP模板题)

    我的第一道KMP. 把两个数列分别当成KMP算法中的模式串和目标串,这道题就变成了一个KMP算法模板题. #include<stdio.h> #include<string.h> ...

  4. HDU 1711 Number Sequence(KMP裸题,板子题,有坑点)

    Number Sequence Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  5. HDU 1711 - Number Sequence - [KMP模板题]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1711 Time Limit: 10000/5000 MS (Java/Others) Memory L ...

  6. HDU 1711 Number Sequence (字符串匹配,KMP算法)

    HDU 1711 Number Sequence (字符串匹配,KMP算法) Description Given two sequences of numbers : a1, a2, ...... , ...

  7. 13-Oulipo(kmp裸题)

    http://acm.hdu.edu.cn/showproblem.php?pid=1686 Oulipo Time Limit: 3000/1000 MS (Java/Others)    Memo ...

  8. zstu.4194: 字符串匹配(kmp入门题&& 心得)

    4194: 字符串匹配 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 206  Solved: 78 Description 给你两个字符串A,B,请 ...

  9. hdu 5288||2015多校联合第一场1001题

    pid=5288">http://acm.hdu.edu.cn/showproblem.php?pid=5288 Problem Description OO has got a ar ...

随机推荐

  1. CSS-三栏响应式布局(左右固宽,中间自适应)的五种方法

    代码: <!-- 1 float --> <h3 class="block">第一种方法-float</h3> <div class=&q ...

  2. 数据结构学习(shell排序和归并排序)

    # coding=utf-8 # shell排序 # 参数alist:被被排序的列表 def shellsort(alist): gap = len(alist) / 2 while gap > ...

  3. spring mvc:事务引起的try/catch失效

    在测试一个接口时,发现一个奇怪的现象:该接口使用@ResponseBody注解返回json格式数据,并且使用try/catch包括全部逻辑代码,debug后发现返回数据没有任何错误,只包含一段因产生异 ...

  4. 第1阶段——uboot分析之硬件初始化start.S(4)

    分析uboot第一个执行函数_start(cpu/arm920t/start.S) 打开cpu/arm920t/start.S .globl _start // .globl定义一个全局符号" ...

  5. poj 3177-3352边双联通

    买一送一啊  3177和3352的区别在于3177数据有重边!但是我先做3177的  那么就直接ctrl+c+v搞3352了~. 题意:给一个无向图,要令每个点之间至少有两条不重合的路,需要至少加多少 ...

  6. 基于AXI4总线卷积FPGA加速IP核的尝试

    本文先总结不同AXI IP核的实现的方法,性能的对比,性能差异的分析,可能改进的方面.使用的硬件平台是Zedboard. 不同的AXI总线卷积加速模块的概况 这次实现并逐渐优化了三个版本的卷积加速模块 ...

  7. Ubuntu操作系统下安装JDK、tomcat、mysql

    1.先从安装虚拟机开始 01.首先打开VMware虚拟机.     02.然后,进入home主页,点击"create a New Virtual Machine"一栏,就会弹出一个 ...

  8. 集美大学网络1413第八次作业(团队四)-- 第一次项目冲刺(Alpha版本)成绩

    首先非常抱歉,刚休完假,凌晨才回来,导致这么晚发布成绩,以后旅行可以考虑带点轻便点的笔记本~ O(∩_∩)O 第一次项目冲刺结束了,可以看出来,有的团队做的很棒,也有的团队组合不是很理想,导致进度一直 ...

  9. 《Java程序设计》第1周学习总结

    1.本周本章学习总结 感觉装环境和基础语言也没什么好总结的,就谈谈我对java的认识. 接触的语言也不多,c语言,python.去年科研立项立了个安卓开发的项.也有去学了一阶段java.由于种种原因没 ...

  10. 201521123034《Java程序设计》第十一周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 多线程的冲突 互斥共享(有时两个或两个以上的线程需要同时对 而线程之间如果不加以控制,会产生一种情况-竞争) sy ...