Tyvj1068 给定两个长度为2*10^5的字符串为A和B 求B在A中匹配后,任意匹配长度的位置个数。

KMP算法大家应该烂熟于心才好,这样碰到这样的题才能灵活运用。有时做题真的需要一点灵感。
首先,这个题如果想要求出从每个位置开始的字串的匹配长度,那么O(n^2)以内的算法应该是很难的。但是,这个题要求的并不是“每个位置的长度”,而是“具有这样长度的位置数”。因而,灵活使用KMP算法自我匹配的性质,就能够解决这个问题。

考虑下面的例子:
A串:abbabbabababbababba
B串:abbabababba

应用KMP算法,很容易得到B串的自我匹配是
元素 a b b a b a b a b b  a
位置 1 2 3 4 5 6 7 8 9 10 11
长度 0 0 0 1 2 1 2 1 2 3  4
这个数组记为kmp[位置] = 匹配长度。

由此求得到A串的各个元素尾部的匹配长度是
a b b a b b a b a b a b b  a  b a b b a
1 2 3 4 5 3 4 5 6 7 8 9 10 11 5 6 7 3 4

统计出各个长度的出现频数
长度 0 1 2 3 4 5 6 7 8 9 10 11
频数 0 1 1 3 3 3 2 2 1 1 1  1
这个数组记作cnt[长度] = 频数。

根据KMP自我匹配数组的性质,如果以A串某个元素结尾有一个长度为11的字串可以与B串匹配的话,以该元素结尾的长度为kmp[11] = 4的字串也是可以匹配的。所以说cnt[4] += cnt[11]。也就是说,进行这样的操作

for (i = N; i >= 1; i--)
    cnt[kmp[i]] += cnt[i];

for i := N downto 1 do
  inc( cnt[ kmp[i] ] , cnt[i] );

之后,cnt[i]中保存的就应该是所有长度为i的匹配字串了。这时cnt数组的状态是

长度 0  1 2 3 4 5 6 7 8 9 10 11
频数 19 8 7 4 4 3 2 2 1 1 1  1

然而题中要求的是“长度恰好为i”的子串的个数,也就是这些字串的下一个字符是不能匹配的。然而,cnt数组中存储的cnt[i],必然包含了cnt[i + 1]及以上的情况。然而这很简单,“长度恰好为i”的字串数量就是cnt[i] - cnt[i + 1],因为cnt[i]中可以扩展的字串必然都包含于cnt[i + 1]。

时间复杂度O(M + N)。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=200000;
char a[maxn],b[maxn];
int la,lb,kmp[maxn],an[maxn],times[maxn];
int main()
{
freopen("t.txt","r",stdin);
ios::sync_with_stdio(false);
int i,j,k,m,n,t;
cin>>la>>lb>>m;
cin>>a>>b;
memset(kmp,0,sizeof(kmp));
for(i=1;i<lb;i++)
{
k=kmp[i-1];
while(k>0&&b[k]!=b[i])
k=kmp[k-1];
if(b[k]==b[i])
kmp[i]=k+1;
else kmp[i]=0;
}
k=0;
memset(an,0,sizeof(an));
for(i=0;i<la;i++)
{
do
{
if(a[i]==b[k])
{
k++;
break;
}
else k=kmp[k-1];
}while(k>0);
if(a[i]==b[k]&&k==0)an[i]=++k;
else an[i]=k;
}
memset(times,0,sizeof(times));
for(i=0;i<la;i++)
times[an[i]]++;
for(i=lb;i>=1;i--)
times[kmp[i-1]]+=times[i];
for(i=1;i<=m;i++)
{
cin>>j;
cout<<times[j]-times[j+1]<<endl;
}
return 0;
}

  

Tyvj 1068 巧用扩展KMP的更多相关文章

  1. 【kmp或扩展kmp】HDU 6153 A Secret

    acm.hdu.edu.cn/showproblem.php?pid=6153 [题意] 给定字符串A和B,求B的所有后缀在A中出现次数与其长度的乘积之和 A和B的长度最大为1e6 方法一:扩展kmp ...

  2. 扩展KMP算法

    一 问题定义 给定母串S和子串T,定义n为母串S的长度,m为子串T的长度,suffix[i]为第i个字符开始的母串S的后缀子串,extend[i]为suffix[i]与字串T的最长公共前缀长度.求出所 ...

  3. 扩展KMP --- HDU 3613 Best Reward

    Best Reward Problem's Link:   http://acm.hdu.edu.cn/showproblem.php?pid=3613 Mean: 给你一个字符串,每个字符都有一个权 ...

  4. KMP和扩展KMP

    文章网上太多这里提一下代码细节: KMP: scanf("%s\n",s); scanf("%s\n",t); int ls=strlen(s),lt=strl ...

  5. UVA5876 Writings on the Wall 扩展KMP

    扩展KMP的简单题. #include<stdio.h> #include<string.h> #define maxn 51010 char s[maxn],t[maxn]; ...

  6. hdu4333 扩展KMP

    慢慢研究可以发现,可以用扩展kmp来求.由于扩展kmp的next[]只有一部分,当前位子前面那部分和母串的后部分,所以可以将字符串复制接在后面一次. 先求如果next[]>0&& ...

  7. 扩展KMP

    刘雅琼论文 http://wenku.baidu.com/view/8e9ebefb0242a8956bece4b3.html 论文讲的非常详细. 给定母串S,子串T,n=strlen(S),m=st ...

  8. HDU 3336 扩展kmp

    题目大意: 找到字符串中所有和前缀字符串相同的子串的个数 对于这种前缀的问题,通常通过扩展kmp来解决 其实吧这是我第一次做扩展kmp的题目,原来确实看过这个概念,今天突然做到,所以这个扩展kmp的模 ...

  9. acdream1116 Gao the string!(扩展KMP)

    今天是字符串填坑的一天,首先填的第一个坑是扩展KMP.总结一下KMP和扩展KMP的区别. 在这里s是主串,t是模式串. KMP可以求出的是以s[i]为结尾的串和 t前缀匹配的最长的长度.假如这个长度是 ...

随机推荐

  1. CodeFrist基础_迁移更新数据

    一丶自动迁移 第一次启用迁移:NeGet-->Enable-Migrations public DemoDbContext() : base("name=ConncodeFirst&q ...

  2. 【转载】eclipse设置护眼色详细教程

    先上一张效果图:     下面开始设置: 首先设置代码区的背景色: Window–>preference-->General-->Editors-->Test Editors ...

  3. Linux(Centos7)下搭建SVN服务器(新手上路)

    以前都是别人直接给地址在svn上,下载或者上传东西,如今要自己建一个版本库用来存放东西.1.安装svnyum install -y subversion 2.查看svn安装位置还有哪些文件rpm -q ...

  4. Unity中带有alpha通道的视频叠加播放

    问题: 如何让两个透明视频叠加播放 解决播放: 1:使用Unity自带的shader,shader代码如下所示 Shader "Unlit/MaskVideo" { Propert ...

  5. vue启动

    首先在终端terminal连上npm 镜像库 npm config set registry https://registry.npm.taobao.orgnpm installnpm run loc ...

  6. 模板—splay

    #include<iostream> #include<cstdio> #define cin(x) scanf("%d",&x) using na ...

  7. selenium爬虫设置headers,代理IP等方法

    https://blog.csdn.net/xc_zhou/article/details/80823855

  8. 洛谷—— P1450 [HAOI2008]硬币购物

    P1450 [HAOI2008]硬币购物 硬币购物一共有$4$种硬币.面值分别为$c1,c2,c3,c4$.某人去商店买东西,去了$tot$次.每次带$di$枚$ci$硬币,买$si$的价值的东西.请 ...

  9. 搭建私有docker仓库

    安装docker yum install docker 启动docker systemctl start docker 拉取registry镜像 docker pull registry 创建仓库配置 ...

  10. stall and flow separation on airfoil or blade

    stall stall and flow separation Table of Contents 1. Stall and flow separation 1.1. Separation of Bo ...