acdream1116 Gao the string!(扩展KMP)
2024-10-12 05:42:32
今天是字符串填坑的一天,首先填的第一个坑是扩展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;
}
最新文章
- django 进阶篇
- 安装完MySQL数据库,在服务列表里找不到MySQL的解决办法
- rbegin 和 end 区别
- 两款HTTP流量分析工具HttpWatch与Fiddler的比较(转)
- 关于LINUX权限-bash: ./startup.sh: Permission denied
- 重构21-Collapse&#160;Hierarchy(去掉层级)
- leetcode第一刷_Construct Binary Tree from Preorder and Inorder Traversal
- 伪元素::before和::after
- asp.net Form 认证【转】
- Weekly Contest 75题解
- Java基础练习1(数据类型转换)
- GetPathFromUri4kitkat【Android 4.4 kitkat以上及以下根据uri获取路径的方法】
- sqlserver全文检索
- Linux打开文件设置
- iOS开发之Xcode9报错 Compiling IB documents for earlier than iOS7 is no longer supported.
- [转]C和C++运行时库
- Oracle数据文件转移操作
- mysql主从配置思路
- 封装之property,多态,鸭子类型,classmethod与staticmethod
- TP3.2加载外部PHPexcel类,实现导入和导出
热门文章
- Moses创建一个翻译系统的基本过程记录,以后会按照每个过程详细说明,并给出每个步骤的参数说明
- VS2005内存泄漏检测方法[转载]
- VBA在WORD中给表格外的字体设置为标题
- 九度oj 1521 二叉树的镜像
- 三星Galaxy Note 10.1 N8010 最后的救赎 Andorid 5.0.2 ROM
- 在线演示平台 | Highcharts中文网 (曲线图、区域图、3D图等等)
- [转]coredump简介与coredump原因总结
- Matlab实现加性高斯白噪声信道(AWGN)下的digital调制格式识别分类
- Linux C 文件与目录2 文件的打开与关闭
- C++中的抽象类及纯虚函数的实现与否