链接:

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3587

题目大意:

给字符串S,T,   找到所有的tetrad (a,b,c,d), Sa..b + Sc..d = T , a≤b and c≤d.

其实就是把T分成两段,这两段都由S中的子串组成的,求有多少中组合方式(S中的两个子串可重叠)。

分析与总结:

这题的AC是我最近几天最高兴的一个AC,因为dp题现在还做得少只会一些基本模型,对dp有种畏惧感,而这题就运用了dp的思想,结果乱搞搞出来了......

我的思路:

设T的长度为len, T可以有前缀T1,后缀T2。

按照长度来分类的话, T1的长度可以为1,2,3...len-1, 相应的T2的长度也可以为1,2,3..len-1。

假设有了一个长度为x的T1, 为了拼凑成完整的T,就要找一个长度为len-x的后缀T2。

那么,在S中有子串T1,T2,cnt1【i】表示长度为i的T1的数量,同理cnt2【i】表示长度为i的T2的数量, 那么,所有的拼凑方案就是 sum =  cnt1[1]*cnt2[len-1]+cnt1[2]*cnt2[len-2]+....cnt[len-1]*cnt[1]。

知道了上述结论,那么现在的关键就是求S中的各种长度的匹配串T1和T2的数量。

我的方法是用拓展KMP, 求出S中的所有后缀的与T的前缀最长公共子串长度,extend【i】表示S【i】开始的与T的前缀的最长公共串,根据这些长度,可以可以确定T1的数量。 假设S=“aabcde”, T="abcge", 那么extend[0] = 1, extend[1]=3...

然后是求后缀T2, 可以把S和T全都转置,倒过来存,然后用同样的方法求出T2数量。

但是有了extend数组还不够,需要求出所有长度的T1,T2数量,这一步就用了dp的思想。

我们可以知道:

extend[i] = 2时,  这个2同时也包含着1的串。

extend[i] = 3时,这个3同时也包含这2,1的串。

extend[i] = 4时,这个4同时也包含着3,2,1的串。

extend[i] = 5时,这个5同时也包含着4,3,2,1的串。

。。。

所以先直接把这些extend的数量先放到cnt里,再这样计算(实在不知道怎样描述,就放代码):

       for(int i=0; S[i]; ++i){if(extend1[i]){++cnt1[extend1[i]];}if(extend2[i]){++cnt2[extend2[i]];}}for(int i=len-1; i>=1; --i){cnt1[i] += cnt1[i+1];cnt2[i] += cnt2[i+1];}

之后,就直接可以根据公式算出答案了。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;typedef long long int64;
const int MAXN = 200005;
char S[MAXN];
char T[MAXN];
int  f[MAXN];
int64  cnt1[MAXN], cnt2[MAXN];
int  extend1[MAXN], extend2[MAXN];void getNext(char* T,int* next){int len=strlen(T), a=0;next[0] = len;while(a<len-1 && T[a]==T[a+1])++a;next[1] = a;a=1;for(int k=2; k<len; ++k){int p=a+next[a]-1, L=next[k-a];if(k-1+L >= p){int j=max(p-k+1,0);while(k+j<len && T[k+j]==T[j]) ++j;next[k] = j;a=k;}else next[k] = L;}
}void EKMP(char* S,char* T,int* next, int* extend){getNext(T,next);int slen=strlen(S), tlen=strlen(T), a=0;int minlen=min(slen,tlen);while(a<minlen && S[a]==T[a])++a;extend[0] = a;a=0;for(int k=1; k<slen; ++k){int p=a+extend[a]-1, L=next[k-a];if(k-1+L >= p){int j=max(p-k+1,0);while(k+j<slen && j<tlen && S[k+j]==T[j]) ++j;extend[k] = j;a=k;}elseextend[k] = L;}
}int main(){int nCase;scanf("%d",&nCase);while(nCase--){memset(S, 0, sizeof(S));memset(T, 0, sizeof(T));scanf("%s %s",S,T);EKMP(S,T,f,extend1);int len=strlen(S);for(int i=0,k=len-1; i<len/2; ++i,--k){char ch=S[i];S[i] = S[k];S[k] = ch;}len=strlen(T);for(int i=0, k=len-1; i<len/2; ++i,--k){char ch=T[i];T[i] = T[k];T[k] = ch;}EKMP(S,T,f,extend2);memset(cnt1, 0, sizeof(cnt1));memset(cnt2, 0, sizeof(cnt2));for(int i=0; S[i]; ++i){if(extend1[i]){++cnt1[extend1[i]];}if(extend2[i]){++cnt2[extend2[i]];}}for(int i=len-1; i>=1; --i){cnt1[i] += cnt1[i+1];cnt2[i] += cnt2[i+1];}long long ans=0;for(int i=1; i<len; ++i)ans += cnt1[i] * cnt2[len-i];printf("%lld\n",ans);}return 0;
}


 ——  生命的意义,在于赋予它意义士。

          原创 http://blog.csdn.net/shuangde800 , By   D_Double  (转载请标明)

zoj 3587 Marlon's String(拓展KMP+dp)相关推荐

  1. ZOJ 3587 Marlon's String 扩展KMP

    链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3587 题意:给出两个字符串S和T,S,T<=100000.拿出 ...

  2. Zoj 3587 Marlon's String (KMP 字符串拼接 前缀出现次数)

    题意:给字符串S,T,找到所有的tetrad (a,b,c,d), Sa..b + Sc..d = T , a≤b and c≤d.也就是把T分成两段,这两段都由S中的子串组成的,求有多少中组合方式( ...

  3. ZOJ 3587 Marlon's String

    KMP,每匹配到一点就记录一下,然后用fail数组把已经匹配到的但是kmp没有记录的点加上.... Marlon's String Time Limit: 2000MS   Memory Limit: ...

  4. [zoj 3587]Marlon's String[kmp]

    题意: Return the amount of tetrad (a,b,c,d) which satisfy Sa..b + Sc..d = T , a≤b and c≤d. 思路: 正反两次kmp ...

  5. ZOJ 3587 Marlon#39;s String 扩展KMP

    链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3587 题意:给出两个字符串S和T.S,T<=100000.拿出 ...

  6. HDU 3336 Count the string(KMP+DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3336 题意:给你一个字符串,计算其所有前缀在该字符串出现的次数的总和. 思路:next[j]=i,代表 ...

  7. UVa11022 String Factoring(kmp+dp)

    用dp(i,j)表示子串s[i..j]可以表示的最小长度.动态转移方程有 dp(i,j) = min{dp(i,k) + dp(k+1,j)},其中k属于[i,j].s[i..j]是周期串,最小周期为 ...

  8. 【ZOJ3587】Marlon's String——白四爷×KMP 白濑肆の算法完全解读KMP篇 KMP来袭第二弹前缀什么的果然最讨厌了!【1.0%达成!】

    #include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> ...

  9. 【总结】字符串匹配: KMP 和 拓展KMP

    比起ac自动机,kmp就一个next数组,理解了如何初始化next后就可以搞一些模板题了,下面是还不错的学习资料,清晰易懂,自己用的模板也来自它: http://chaoswork.com/blog/ ...

最新文章

  1. c语言关键字不做标识符,C语言标识符、关键字、注释、表达式和语句
  2. iOS自动布局(AutoLayout)之 NSLayoutAnchor
  3. 苹果发布新手机,会有多少国人支持呢?
  4. qt mysql查询中文相等_请教:Qt如何实现查询数据库中具有中文表名的表
  5. 一个DEMO让你彻底理解线程池
  6. 一企业靠数据中台打通SAP、ERP系统,还能做出可视化分析
  7. hadoop使用combiner合并操作
  8. ZedGraph设置辅助线
  9. android 仿美团悬浮,类似美团悬浮框的效果
  10. SVN部署与简单使用
  11. 摄氏温度和华氏温度换算(vb源码)
  12. 学成在线案例(完整代码)
  13. [GRE] 填空机经 Section61-65
  14. 对倒立摆的LQR控制
  15. IIS EXPRESS无法启动
  16. 计算机键盘交替换键是,用了这么久电脑,还不知道键盘上的Ctrl、Tab、Alt是啥英文?快来涨知识!...
  17. 态度决定一切《跟任何人都聊得来》
  18. 企业网站制作多少钱、企业网站需要多少钱、建立网站需要花多少钱
  19. 要数字孪生实现,你只需这款数据可视化大屏软件就够了
  20. 年老时最后悔但为时已晚的几件事

热门文章

  1. ios dat 文件读写_iOS数据恢复前沿探索
  2. java image写入文件,从文件读取/写入图像到BufferedImage的最快方法?
  3. 2019.6.14 巴塞尔问题
  4. onlyoffice文档服务器安装,CentOS7部署OnlyOffice在线办公服务器
  5. PDF转TXT免费脚本
  6. @kubernetes(k8s)pod服务探针(健康检查)及回调钩子HOOK详解
  7. 安徽省二级计算机考试大纲,安徽省计算机省二级考试大纲
  8. 解决PS 内存不足,RAM不足问题,方案汇总
  9. 枢轴点(Pivot Point)系统
  10. 2021爱智先行者—数量遗传学 第一章 数量遗传学概论