扩展KMP题目
hdu4333
/*
题意:字符串s[0..n-1],每次把最后一个字符放到前面,求形成的字符串比最初串分别小,相同,大于的个数
因为是为了练习扩展KMP所以肯定是扩展KMP,
为了循环方便,在后面复制字符串,求出next[]数组后,
如果next[i]>n那么肯定相等,如果小于就判断s[ next[i] ]和 s[ i+next[i] ]的大小判断 trick:题目求得是形成的不同的字符串的个数,可以知道相等的字符串肯定只有一个,
而从0..n-1,第二个next[i]大于n那么这个i就是该字符串的循环节;
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
const int N=+;
char s[N*];
int next[N*],n; void getNext(char *s,int next[]){
int nn=strlen(s);
next[]=nn;
int p=;
while (s[p+] && s[p]==s[p+]) p++;
next[]=p;
int k=;
for (int i=;i<nn;i++){
int p=k+next[k]-, L=next[i-k];
if (i+L<=p) next[i]=L;
else{
int j=p-i+;
if (j<) j=;
while (i+j<nn && s[i+j]==s[j]) j++;
next[i]=j; k=i;
}
} } void work(){
int ret1,ret2,ret3;
ret1=ret2=ret3=;
getNext(s,next);
for (int i=;i<n;i++){
if (i!= && next[i]>=n) break;
if (next[i]<n) {
if (s[ i+next[i] ]<s[ next[i] ]) ret1++;
else ret3++;
}else ret2++;
}
printf("%d %d %d\n",ret1,ret2,ret3);
}
int main(){
int T,cas=;scanf("%d",&T);
while (T--){
scanf("%s",s);
printf("Case %d: ",++cas);
n=strlen(s);
for (int i=;i<n;i++){
s[n+i]=s[i];
}s[n+n]='\0';
// cout<<s<<endl;
work();
}
return ;
}
hdu3613
/*
题意:将一个串分成俩个串,如果是回文串值就是所有字符的值,如果不是值就为0
问你最大的值是多少; 分析:因为是扩展KMP的题,很容易想到用扩展KMP判读是否是回文串,而且题目的
特点是至少有一端是端点,这很容易想到前缀和后缀,然后思路就出来了;
首先将串s逆转变成s1,求出s的所有后缀与s1的最长公共子串的长度,
这样分割成两段的后面一段,判断该段是否是回文只要判断最长长度是否等于后面一段的 长度就可以了了
前面一段类似,只是要求出s1的所有后缀与s的最长公共子串的长度,判断方法类似 */
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
const int N=+;
char s[N],s1[N];
int v[];
int ext1[N],ext2[N],next[N];
void getNext(char *s,int next[]){
int nn=strlen(s);
next[]=nn;
int p=;
while (s[p+] && s[p]==s[p+]) p++;
next[]=p;
int k=, L;
for (int i=;i<nn;i++){
p=k+next[k]-; L=next[i-k];
if (i+L<=p) next[i]=L;
else {
int j=p-i+;
if (j<) j=;
while (i+j<nn && s[i+j]==s[j]) j++;
next[i]=j; k=i;
}
} }
void getExtend(char *s,char *T,int *ext){
getNext(s,next);
int p=, nn=strlen(s);
while (s[p] && s[p]==T[p]) p++;
ext[]=p;
int k=, L;
for (int i=;i<nn;i++){
p=k+ext[k]-; L=next[i-k];
if (i+L<=p) ext[i]=L;
else {
int j=p-i+;
if(j<) j=;
while (i+j<nn && s[i+j]==T[j]) j++;
ext[i]=j; k=i;
}
}
}
int val[N];
void work(){
memset(val,,sizeof(val));
int len=strlen(s);
for (int i=;i<len;i++) val[i+]=val[i]+v[s[i]-'a']; for (int i=len-;i>=;i--) s1[len-i-]=s[i];
s1[len]='\0';
// cout<<s<<endl<<s1<<endl;
getExtend(s1,s,ext1);
getExtend(s,s1,ext2); int ret=;
for (int i=;i<len;i++){
int l1=i,l2=len-l1;
int tmp=;
if (ext1[len-i]==l1) tmp+=val[i];
if (ext2[i]==l2) tmp+=val[len]-val[i];
if (tmp>ret) ret=tmp;
}
printf("%d\n",ret);
}
int main(){
int T;scanf("%d",&T);
while (T--){
for (int i=;i<;i++) scanf("%d",v+i);
scanf("%s",s);
work();
}
return ;
}
/*
4
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
aaadbbbd
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
ab
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
aba
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
aaaaaaaaaaaaaaa */
poj1699
/*
题意:给你n个串,求最短的串使得n个串都包含在里面(n<=10)
从n的数据范围就可以看出状态压缩dp
dp[i][j]表示已经包含了"i"个串,且最后一个串是j的最小长度
预处理出s[i]的后缀与s[j]的前缀的最长公共子串 */
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
const int N=+;
char s[N][N];
int n,next[N],mz[N][N],ext[N];
void getNext(char *s,int *next){
int nn=strlen(s);
next[]=nn;
int p=;
while (s[p+] && s[p]==s[p+]) p++;
next[]=p;
int k=, L;
for (int i=;i<nn;i++){
p=k+next[k]-; L=next[i-k];
if (i+L<=p) next[i]=L;
else{
int j=p-i+;
if (j<) j=;
while (i+j<nn && s[i+j]==s[j]) j++;
next[i]=j; k=i;
}
}
}
void getExtend(char *s,char *T,int ext[]){
getNext(s,next);
int nn=strlen(s);
int p=;
while (s[p] && T[p] && s[p]==T[p]) p++;
ext[]=p;
int k=,L;
for (int i=;i<nn;i++){
p=k+ext[k]-; L=next[i-k];
if (i+L<=p) ext[i]=L;
else {
int j=p-i+;
if (j<) j=;
while (i+j<nn && s[i+j]==T[j]) j++;
ext[i]=j; k=i;
}
}
}
void init(){
memset(mz,,sizeof(mz));
for (int i=;i<n;i++){
for (int j=;j<n;j++){
if (i==j) continue;
getExtend(s[i],s[j],ext);
int nn=strlen(s[i]);
for (int k=;k<nn;k++){
if (ext[k]==nn-k) {
mz[i][j]=nn-k; break;
}
}
}
}
/*for (int i=0;i<n;i++){
for (int j=0;j<n;j++){
cout<<mz[i][j]<<" ";
}cout<<endl;
}*/
}
const int NN=<<;
int dp[NN][];
void Min(int &x,int y){
if (x==-) x=y;
else x=min(x,y);
}
void work(){
memset(dp,-,sizeof(dp));
for (int i=;i<n;i++){
dp[<<i][i]=strlen(s[i]);
}
for (int i=;i<(<<n);i++){
for (int j=;j<n;j++){
if (dp[i][j]==-) continue;
for (int k=;k<n;k++){
if ( i&(<<k) ) continue;
Min(dp[i^(<<k)][k],dp[i][j]+strlen(s[k])-mz[j][k]);
}
}
}
int ret=-;
for (int i=;i<n;i++){
Min(ret,dp[(<<n)-][i]);
}
cout<<ret<<endl; }
int main(){
int T;scanf("%d",&T);
while (T--){
scanf("%d",&n);
for (int i=;i<n;i++) scanf("%s",s[i]);
init();
work();
}
return ;
}
扩展KMP题目的更多相关文章
- hdu4333 扩展KMP
慢慢研究可以发现,可以用扩展kmp来求.由于扩展kmp的next[]只有一部分,当前位子前面那部分和母串的后部分,所以可以将字符串复制接在后面一次. 先求如果next[]>0&& ...
- HDU 3336 扩展kmp
题目大意: 找到字符串中所有和前缀字符串相同的子串的个数 对于这种前缀的问题,通常通过扩展kmp来解决 其实吧这是我第一次做扩展kmp的题目,原来确实看过这个概念,今天突然做到,所以这个扩展kmp的模 ...
- 【GDOI2014 DAY2】Beyond (扩展KMP)
[题目] [题意] Jodie和Aiden在做游戏.Jodie在一个长度为l字符串环上走路,他每离开一个就会记下格子当前字符.他让Aiden在他走了一圈后叫他停下来.Aiden决定耍一下Jodie,在 ...
- HDU 4333 Revolving Digits 扩展KMP
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4333 题意:给以数字字符串,移动最后若干位到最前边,统计得到的数字有多少比原来大,有多少和原来同样,有多少 ...
- HDU 3613 Best Reward 正反两次扩展KMP
题目来源:HDU 3613 Best Reward 题意:每一个字母相应一个权值 将给你的字符串分成两部分 假设一部分是回文 这部分的值就是每一个字母的权值之和 求一种分法使得2部分的和最大 思路:考 ...
- (简单) POJ 1961 Period,扩展KMP。
Description For each prefix of a given string S with N characters (each character has an ASCII code ...
- A - A Secret -扩展KMP
题目大意: 给你两个字符串A,B,现在要你求B串的后缀在A串中出现的次数和后缀长度的乘积和为多少. 题解: 扩展KMP模板题,将A和B串都逆序以后就变成了求前缀的问题了,扩展KMP求处从i位置开始的最 ...
- HDU-6153 A Secret 扩展KMP
题意:求一个字符串的所有后缀在母串中的出现次数*后缀的长度的总和. 题目链接:http://acm.split.hdu.edu.cn/viewcode.php?rid=22147273 思路:先预处理 ...
- hdu 4300 Clairewd’s message(扩展kmp)
Problem Description Clairewd is a member of FBI. After several years concealing in BUPT, she interce ...
随机推荐
- [51NOD1105]第k大的数(二分答案)
题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1105 先排序,二分上下界分别是最小的两个数和最大的两个数的乘积 ...
- Oracle的rownum原理和使用(整理几个达人的帖子)
整理和学习了一下网上高手关于rownum的帖子: 参考资料: http://tech.ddvip.com/2008-10/122490439383296.html 和 http://tenn.jav ...
- 类Item_equal
class Item_equal: public Item_bool_func { List<Item_field> fields; /* list of equal field item ...
- onkeypress与onkeydown及 oncopy和onpaste 事件区别详细说明
onkeypress与onkeydown 具体区别: 1. 一个放开一个没有放开,onkeydown 先于 onkeypress 发生. 2.onkeypress 无法系统按钮. 2.onkeydow ...
- Jquery 模板插件 jquery.tmpl.js 的使用方法(2):嵌套each循环,temp调用(使用预编译的模板缓存)
直接上代码吧 一:主窗口 /*#region SendChooseTargetTemplate 发送候选人主窗口模板*/ var SendChooseTargetTemplate = ''; Send ...
- jfinal框架教程-学习笔记(一)
JFinal 是基于 Java 语言的极速 WEB + ORM 开发框架,其核心设计目标是开发迅速.代码量少.学习简单.功能强大.轻量级.易扩展.Restful.在拥有Java 语言所有优势 ...
- uvalive 3523 Knights of the Round Table 圆桌骑士(强连通+二分图)
题目真心分析不出来.看了白书才明白,不过有点绕脑. 容易想到,把题目给的不相邻的关系,利用矩阵,反过来建图.既然是全部可行的关系,那么就应该能画出含奇数个点的环.求环即是求双连通分量:找出所有的双连通 ...
- RTP/RTCP(一)-H264关于RTP协议的实现
H264关于RTP协议的实现2010-07-22 13:35完整的C/S架构的基于RTP/RTCP的H.264视频传输方案.此方案中,在服务器端和客户端分别进行了功能模块设计.服务器端:RTP封装模块 ...
- session服务器Nginx+Tomcat+Memcached集群Session共享
cookie是怎样工作的? 例如,我们创立了一个名字为login的Cookie来包含访问者的信息,创立Cookie时,服务器端的Header如下面所示,这里假设访问者的注册名是“Michael Jor ...
- <三>面向对象分析之UML核心元素之参与者
一:版型 --->在UML里有一个概念叫版型.有些书里也称类型,构造型. --->这个概念是对一个UML元素基础定义的扩展.在同一个元素基础定义的基础上赋予特别 ...