逆序KMP,真的是强大!

参考链接,下面有题意解释:
http://blog.sina.com.cn/s/blog_6ec5c2d00100tphp.html
http://blog.csdn.net/sdjzping/article/details/8857749
http://tech.ddvip.com/2013-09/1380477442203505.html

直接暴力是枚举字符串的后面13个的字母,然后再用KMP匹配,这样的话,就绪要枚举多次,分别是后面的13,12,11....1个字母。
但是通过观察可以发现,其实要求的是最长公共后缀! 那么可以把原来的字符串逆序转换一下,就变成了求最长公共前缀!
这样只需要求一次,用字符串的前面13个字母和原字符串从第二个字符开始进行匹配一次就够了!

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string>
#include <string.h> using namespace std;
const int maxn=+;
char s[maxn],str[maxn];
int next[maxn];
char ans[]; //答案
int n,l;
int start=; //标记字符串的起始位置
int k; void getNext(char*str) {
next[]=;
int k=;
int lm=strlen(str);
for(int i=; i<lm; i++) {
while(k&&str[k]!=str[i])
k=next[k];
if(str[i]==str[k])
k++;
next[i+]=k;
}
}
//逆序KMP,转化为求最长公共前缀
int kmp(char*P,int len) {
int k=,c=,idx;
int lm=strlen(P);
for(int i=start+; i<start+len; i++) {
while(k&&P[k]!=str[i])
k=next[k];
if(P[k]==str[i])
k++;
if(k>c){
c=k;
idx=i;
}
if(k==lm)
return i-k;
}
if(c)
return idx-c;
else
return -;
}
int main()
{
char tmp[];
scanf("%d%d",&n,&l);
scanf("%s",&s);
int len=strlen(s);
for(int i=;s[i];i++){
str[start+i]=s[len--i];
}
str[start+len]='\0';
int cnt=l,k;
while(cnt--){
//截取开始的13个字符
strncpy(tmp,str+start,);
if(len<)
tmp[len]='\0';
else
tmp[]='\0';
getNext(tmp);
k=kmp(tmp,len);
start--;
len++;
if(k==-)
str[start]=''; //不存在匹配的情况
else
str[start]=str[k];
}
for(int i=;i<l;i++)
ans[i]=str[start+l--i];
ans[l]='\0';
printf("%s\n",ans);
return ;
}

POJ 2541 Binary Witch(逆序KMP,好题)的更多相关文章

  1. poj 2541 Binary Witch

    Binary Witch http://poj.org/problem?id=2541 Time Limit: 1000MS   Memory Limit: 65536K       Descript ...

  2. POJ 1840 Brainman(逆序对数)

    题目链接:http://poj.org/problem?id=1804 题意:给定一个序列a[],每次只允许交换相邻两个数,最少要交换多少次才能把它变成非递降序列. 思路:题目就是要求逆序对数,我们知 ...

  3. POJ 2828 线段树 逆序插入

    思路: 1.线段树 逆着插入就OK了 2.块状链表 (可是我并不会写) //By SiriusRen #include <cstdio> #include <cstring> ...

  4. (中等) POJ 2828 Buy Tickets , 逆序+线段树。

    Description: Railway tickets were difficult to buy around the Lunar New Year in China, so we must ge ...

  5. 【poj 1961】Period(字符串--KMP 模版题)

    题意:给你一个字符串,求这个字符串到第 i 个字符为止的重复子串的个数. 解法:判断重复子串的语句很重要!!if (p && i%(i-p)==0) printf("%d % ...

  6. 将单链表的每K个节点之间逆序

    [说明]: 本文是左程云老师所著的<程序员面试代码指南>第二章中“将单链表的每K个节点之间逆序”这一题目的C++复现. 本文只包含问题描述.C++代码的实现以及简单的思路,不包含解析说明, ...

  7. (字符串的处理4.7.16)POJ 1159 Palindrome(让一个字符串变成回文串需要插入多少个字符...先逆序,在减去公共子序列的最大长度即可)

    /* * POJ_1159.cpp * * Created on: 2013年10月29日 * Author: Administrator */ #include <iostream> # ...

  8. poj 2828 Buy Tickets【线段树单点更新】【逆序输入】

    Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 16273   Accepted: 8098 Desc ...

  9. POJ 2299 Ultra-QuickSort (求序列的逆序对数)

    题意:废话了一大堆就是要你去求一个序列冒泡排序所需的交换的次数. 思路:实际上是要你去求一个序列的逆序队数 看案例: 9 1 0 5 4 9后面比它小的的数有4个 1后面有1个 0后面没有 5后面1个 ...

随机推荐

  1. char const*, char*const, const char *const的区别

    C++标准规定,const关键字放在类型或变量名之前等价的.所以,const char*和 char const*是一样的. const char*   //常量指针---指向常量的指针----指针指 ...

  2. C/C++ 对常见字符串库函数的实现

    在c中的string.h头文件中存在很多对字符串进行操作的函数,利用这些函数可以方便的对字符串进行操作.下面将对常见的字符串函数进行解释和实现. strcpy 函数原型:char* _strcpy(c ...

  3. git的工作流程(分支合并)

    git支持很多种工作流程,我们采用的一般是这样,远程创建一个主分支,本地每人创建功能分支,日常工作流程如下: 去自己的工作分支$ git checkout work 工作.... 提交工作分支的修改$ ...

  4. Linux下如何查看JDK安装路径

    1:echo $JAVA_HOME 使用$JAVA_HOME的话能定位JDK的安装路径的前提是配置了环境变量$JAVA_HOME,否则如下所示,根本定位不到JDK的安装路径 [root@localho ...

  5. Python pexpect出现错误‘module have no attribute "spawn" 解决办法

    今天我遇到了这个错误,现在将错误总结如下: 1.首先查询一下自己的操作系统,pexpect中的spawn()和run()仅仅运行在POSIX系统上,在WINDOWS下是没有这两个东西的,在官网http ...

  6. Tutorial: Analyzing sales data from Excel and an OData feed

    With Power BI Desktop, you can connect to all sorts of different data sources, then combine and shap ...

  7. iOS 七大手势之轻拍,长按,旋转手势识别器方法

    一.监听触摸事件的做法   如果想监听一个view上面的触摸事件,之前的做法通常是:先自定义一个view,然后再实现view的touches方法,在方法内部实现具体处理代码 通过touches方法监听 ...

  8. StatusBar & StatusBarItem

    StatusBar & StatusBarItem StatusBar StatusBar class StatusBarItem StatusBarItem class Example &l ...

  9. PB中掉用Run以后,等Run的程序关闭以后才会执行后边的语句

    OleObject wsh integer li_rc CONSTANT integer MAXIMIZED = CONSTANT integer MINIMIZED = CONSTANT integ ...

  10. 利用while(code!=EOF){}来实现“无限”循环

    #include <stdio.h>int main(){    char a,b,c;    char t;    while(scanf("%c%c%c",& ...