今天是字符串填坑的一天,首先填的第一个坑是扩展KMP。总结一下KMP和扩展KMP的区别。

在这里s是主串,t是模式串。

KMP可以求出的是以s[i]为结尾的串和 t前缀匹配的最长的长度。假如这个长度是L的话,则:

s[i-L+1...i]=t[0...L]

而所谓的失配指针f[i]指的就是当前i点失配时要匹配的长度,实际是用t文本串去匹配t。

扩展KMP则是以s[i]为起始的串和 t前缀匹配的最长的长度。 假如这个长度的话,则:

s[i..i+L-1]=t[0...L]

扩展KMP里的nxt数组就是利用t本身和自己匹配达到的效果。所以nxt[i]就是以t的后缀i和t的前缀匹配的最长的长度,有了这个就可以用来求上次的这道题了。

自己写的时候写了个后缀数组的版本,可以将t的前缀理解成后缀0,于是就是后缀之间的最长前缀,就是利用lcp来求,无奈的是后缀数组本身求的速度太慢了,rmq的速度更慢。由于扩展KMP是线性的,所以这次就可以顺利的过了这道坑爹题了。

下面第一个网里有一些理论的证明,但KMP那部分和我学的不太一样,不知道是我搞错了还是版本不一样,然后第二个链接里的代码感觉写的可读性强一点,在这里存一下模板。

http://www.cnblogs.com/10jschen/archive/2012/09/03/2668149.html

http://www.cnblogs.com/kuangbin/archive/2012/08/27/2659246.html

#pragma warning(disable:4996)
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std; #define ll long long
#define mxs 1000000
#define mxt 100000
#define mod 1000000007 char s[mxs], t[mxt]; int nxt[mxt], ex[mxt]; // get the next array for t only
void getNext(char *t,int *nxt)
{
int m = strlen(t);
nxt[0] = m;
int j = 0;
while (j + 1 < m&&t[j] == t[j + 1]) j++;
nxt[1] = j;
int k = 1; int p, L;
for (int i = 2; i < m; i++)
{
p = nxt[k] + k - 1;
L = nxt[i - k];
if (i + L < p + 1) nxt[i] = L; // i+L<=p
else
{
j = max(0, p - i + 1);
while (i + j < m&&t[i + j] == t[0 + j])j++;
nxt[i] = j;
k = i;
}
}
} // get the next array for t, and get the ex array for s;
void getExtend(char *s, char *t, int *nxt, int *ex)
{
getNext(t, nxt);
int n = strlen(s), m = strlen(t);
int j = 0;
while (j < n&&j < m&&s[j] == t[j]) j++;
ex[0] = j;
int k = 0; int p, L;
for (int i = 1; i < n; i++){
p = ex[k] + k - 1;
L = nxt[i - k];
if (i + L < p + 1) ex[i] = L;
else{
j = max(0, p - i + 1);
while (i + j < n&&j < m&&s[i + j] == t[j]) j++;
ex[i] = j;
k = i;
}
}
} struct Matrix
{
ll a[2][2];
Matrix(){ memset(a, 0, sizeof(a)); }
}m; Matrix operator * (const Matrix &a, const Matrix &b){
Matrix ret;
for (int i = 0; i < 2; i++){
for (int j = 0; j < 2; j++){
for (int k = 0; k < 2; k++){
ret.a[i][j] += (a.a[i][k] * b.a[k][j]) % mod;
ret.a[i][j] %= mod;
}
}
}
return ret;
}
Matrix operator ^ (Matrix a, ll n){
Matrix ret;
for (int i = 0; i < 2; i++) ret.a[i][i] = 1;
while (n){
if (n & 1) ret = ret*a;
n >>= 1;
a = a*a;
}
return ret;
} ll cal(ll n)
{
m.a[0][0] = 0; m.a[0][1] = 1;
m.a[1][0] = 1; m.a[1][1] = 1;
m = m^n;
return m.a[0][1];
} int main()
{
while (~scanf("%s",s)){
getNext(s, nxt);
int n = strlen(s);
nxt[n] = 0;
ll ans = 0;
for (int i = n - 1; i >= 0; i--){
nxt[i] += nxt[i + 1];
ans += cal(nxt[i]);
ans %= mod;
}
printf("%lld\n", ans);
}
return 0;
}

acdream1116 Gao the string!(扩展KMP)的更多相关文章

  1. hdu3336 Count the string 扩展KMP

    It is well known that AekdyCoin is good at string problems as well as number theory problems. When g ...

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

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

  3. HDU-3336-Count the string(扩展KMP)

    链接: https://vjudge.net/problem/HDU-3336 题意: It is well known that AekdyCoin is good at string proble ...

  4. acdream1116 Gao the string!(hash二分 or 后缀数组)

    问题套了一个斐波那契数,归根结底就是要求对于所有后缀s[i...n-1],所有前缀在其中出现的总次数.我一开始做的时候想了好久,后来看了别人的解法才恍然大悟.对于一个后缀来说 s[i...n-1]来说 ...

  5. [2019杭电多校第五场][hdu6629]string matching(扩展kmp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6629 题意求字符串的每个后缀与原串的最长公共前缀之和. 比赛时搞东搞西的,还搞了个后缀数组...队友一 ...

  6. 【string】KMP, 扩展KMP,trie,SA,ACAM,SAM,最小表示法

    [KMP] 学习KMP,我们先要知道KMP是干什么的. KMP?KMPLAYER?看**? 正如AC自动机,KMP为什么要叫KMP是因为它是由三个人共同研究得到的- .- 啊跑题了. KMP就是给出一 ...

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

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

  8. UVA5876 Writings on the Wall 扩展KMP

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

  9. hdu4333 扩展KMP

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

随机推荐

  1. Android触摸屏配置调试

    前几天搞乐蛙时,进入后是鼠标模式,好坑爹的模式有木有~~ 但是大蛋给出了解决方法,我不怕不怕啦~让我们向大牛致敬!!! 首先输入Command查看你的input配置~ adb shell dumpsy ...

  2. CSS3中新出现的技术

    CSS3中新出现的技术 CSS媒体查询 媒体查询 包含了一个媒体类型和至少一个使用如宽度.高度和颜色等媒体属性来限制样式表范围的表达式.CSS3加入的媒体查询使得无需修改内容便可以使样式应用于某些特定 ...

  3. malloc calloc realloc,new区别联系以及什么时候用

    三个函数的申明分别是:void* realloc(void* ptr, unsigned newsize);void* malloc(unsigned size);void* calloc(size_ ...

  4. 2天驾驭DIV+CSS (基础篇)(转)

    这是去年看到的一片文章,感觉在我的学习中,有不少的影响.于是把它分享给想很快了解css的兄弟们. 基础篇[知识一] “DIV+CSS” 的叫法是不准确的[知识二] “DIV+CSS” 将你引入两大误区 ...

  5. (转)android Fragments详解一:概述

    Fragment是activity的界面中的一部分或一种行为.你可以把多个Fragment们组合到一个activity中来创建一个多面界面并且你可以在多个activity中重用一个Fragment.你 ...

  6. 关于如何将Excel数据导入到SQL Server中

    面对大量的Excel数据我们可能会非常苦恼,如果一条一条的插入到数据库:不仅会耗大量的时间,而且还可能会发生错误,现在我来说一下如何导入数据! 1.准备工作 首先要在Excel中建立数据表对应的数据字 ...

  7. Visio编辑数据库模型列

    Visio编辑数据库模型列:邮件group->Open实体,进入实体属性编辑界面,按回车可以添加.

  8. 54.xilinx_modelsim仿真错误1

    在仿真DDR3核时,用modelsim编译时会出现下面错误 Error:can't read "env(XILINX)":no such variable 原因:在.do文件中指定 ...

  9. (转)Unity3d中的属性(Attributes)整理

    Attributes属性属于U3D的RunTimeClass,所以加上以下的命名空间是必须的了.其它倒没什么需要注意的.本文将所有运行属性过一遍罢了. using UnityEngine; using ...

  10. SDOI2016 round1滚粗记

    Day -1 刚刚从HN集训回来,感觉整个人萌萌哒.考前不断立flag——这次我一定会滚粗的,然后设想着滚粗之后文化课先补什么,浑浑噩噩的过了一天,晚上看到CA爷(娘)发了关于cena爆栈的问题,这时 ...