hdu 4468 spy 极其精彩的一道kmp灵活运用题
出的超级好的一道题。至于好在哪里,请思考题目:
题意抽象出来为给定一个字符串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灵活运用题的更多相关文章
- 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 ...
- HDU - 4333 :Revolving Digits (扩展KMP经典题,问旋转后有多少个不同的数字小于它本身,等于它本身,大于它本身。)
One day Silence is interested in revolving the digits of a positive integer. In the revolving operat ...
- hdu 1711 Number Sequence(KMP模板题)
我的第一道KMP. 把两个数列分别当成KMP算法中的模式串和目标串,这道题就变成了一个KMP算法模板题. #include<stdio.h> #include<string.h> ...
- HDU 1711 Number Sequence(KMP裸题,板子题,有坑点)
Number Sequence Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- HDU 1711 - Number Sequence - [KMP模板题]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1711 Time Limit: 10000/5000 MS (Java/Others) Memory L ...
- HDU 1711 Number Sequence (字符串匹配,KMP算法)
HDU 1711 Number Sequence (字符串匹配,KMP算法) Description Given two sequences of numbers : a1, a2, ...... , ...
- 13-Oulipo(kmp裸题)
http://acm.hdu.edu.cn/showproblem.php?pid=1686 Oulipo Time Limit: 3000/1000 MS (Java/Others) Memo ...
- zstu.4194: 字符串匹配(kmp入门题&& 心得)
4194: 字符串匹配 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 206 Solved: 78 Description 给你两个字符串A,B,请 ...
- hdu 5288||2015多校联合第一场1001题
pid=5288">http://acm.hdu.edu.cn/showproblem.php?pid=5288 Problem Description OO has got a ar ...
随机推荐
- python条件判断与循环
条件判断 1.python缩进规则: 如果if语句判断是True,就把缩进的语句执行了,否则,什么也不做,比如: age=20 if age >= 18: print('your age is' ...
- mysql转ElasticSearch的案例分析
前言 最近工作中在进行一些技术优化,为了减少对数据库的压力,对于只读操作,在程序与db之间加了一层-ElasticSearch.具体实现是db与es通过bin-log进行同步,保证数据一致性,代码调用 ...
- Java Integer封装类的IntegerCache内部类
个人理解,不喜勿喷,欢迎指正. 首先看下面这段代码,猜一下输出结果是什么 Integer a = 10; Integer b = 10; System.out.println(a == b); a = ...
- 红黑树的插入Java实现
package practice; public class TestMain { public static void main(String[] args) { int[] ao = {5, 1, ...
- LVS之DR模式实战及高可用性
author:JevonWei 版权声明:原创作品 LVS-DR实现同网段调度web模式 拓扑环境 网络环境 RS1 RIP 192.168.198.138/24 VIP 192.168.198.10 ...
- Linux io Model
socket阻塞与非阻塞,同步与异步 作者:huangguisu 1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调 ...
- 浅谈如何用Java操作MongoDB
NoSQL数据库因其可扩展性使其变得越来越流行,利用NoSQL数据库可以给你带来更多的好处,MongoDB是一个用C++编写的可度可扩展性的开源NoSQL数据库.本文主要讲述如何使用Java操作Mon ...
- javascript this对象
函数运行时,自动生成的一个内部对象,只能在函数内部使用 随着函数使用场合的不同,this的值也发生着改变,但是有一个总原则:this指的是调用函数的那个对象(核心) this对象的指向 一般情况下,我 ...
- 【1414软工助教】博客链接和coding链接
某些同学提供的coding.net用户名无法访问.请同学们自己点击自己的两个链接,如果发现有错,请在本博客的评论区给出正确的链接. 格式为: 学号后3位 链接 例如:***502 https://co ...
- 微信小程序swiper标签的测试
swiper属性(具体看官方文档): 一:testswiper.wxml的代码如下.testswiper.js自动生成示例代码. //testswiper.wxml <view > < ...