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

题意抽象出来为给定一个字符串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. 我理解的Java中重载与重写

    程序中我们用方法来实现对对象的操作,但是对象可能有不同的数据类型,这时候对不同的数据类型,进行相同的操作,我们就可以用到方法的重载,即方法名相同,但是具有不同的参数列表. 方法的重载可以根据传递参数的 ...

  2. Ext.grid.EditorGridPanel保存

    用get方法传递编辑的数据会出现乱码,解决get乱码的方法就是encodeURI(param),然后在后台转码: String strJson =  new String(request.getPar ...

  3. MySQL的JOIN(三):JOIN优化实践之内循环的次数

    这篇博文讲述如何优化内循环的次数.内循环的次数受驱动表的记录数所影响,驱动表记录数越多,内循环就越多,连接效率就越低下,所以尽量用小表驱动大表.先插入测试数据. CREATE TABLE t1 ( i ...

  4. tkinter第一章

    tk1 ------------------------------------------------------------------------------------------ impor ...

  5. JPG、PNG和GIF图片的基本原理及优…

    JPG.PNG和GIF图片的基本原理及优化方法 一提到图片,我们就不得不从位图开始说起,位图图像(bitmap),也称为点阵图像或绘制图像,是由称作像素(图片元素)的单个点组成的.这些点可以进行不同的 ...

  6. 全面解析for循环

    牛刀小试: for(var i = 0 ; i < 100; i++) {console.log(i);} var i = 0;//第一个代码段 i < 100; //第二个代码段 i++ ...

  7. 转: 【Java并发编程】之二十:并发新特性—Lock锁和条件变量(含代码)

    简单使用Lock锁 Java5中引入了新的锁机制--Java.util.concurrent.locks中的显式的互斥锁:Lock接口,它提供了比synchronized更加广泛的锁定操作.Lock接 ...

  8. 201521123088《Java程序设计》第6周学习总结

    1. 本周学习总结 2. 书面作业 clone方法1.1 Object对象中的clone方法是被protected修饰,在自定义的类中覆盖clone方法时需要注意什么?                 ...

  9. 201521123065《java程序设计》第12周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 1.流的划分:输入流:字节流(InputStream).字符流(reader): 输出流:字节流(Output ...

  10. 201521123039 《java程序设计》第九周学习总结

    1. 本周学习总结 2. 书面作业 本次PTA作业题集异常 常用异常 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己以前编写的代码中经常出现什么异常.需要捕获吗(为什么)?应如何避免? ...