扩展kmp 学习笔记
2024-10-19 14:20:48
学习了一下这个较为冷门的知识,由于从日报开始看起,还是比较绕的……
首先定义 \(Z\) 函数表示后缀 \(i\) 与整个串的 \(lcp\) 长度
一个比较好的理解于实现方式是类似于 \(manacher\) 维护出 \([l,r]\) 表示能够匹配的最右端是 \(l\) 位置匹配上的到达 \(r\) 的区间
假设目前求到 \(i\):
那么可以发现可以直接由 \(nxt[i-l+1]\) 继承过来,需要和 \(r-i+1\) 取 \(min\)
另一个问题是假如 \(r<i\) 或 \(nxt[i-l+1]\ge r-i+1\),后面的部分需要进行暴力匹配
并且及时更新 \(r\) 的取值
以下是模板实现:
代码实现
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e7+5;
int n,m,nxt[maxn],ex[maxn];
char a[maxn],b[maxn];
long long ans;
void getnxt(){
nxt[1]=m;
for(int i=2,l=0,r=0;i<=m;i++){
if(i<=r)nxt[i]=min(nxt[i-l+1],r-i+1);
while(i+nxt[i]<=m&&b[nxt[i]+i]==b[nxt[i]+1])nxt[i]++;
if(i+nxt[i]-1>r)r=i+nxt[i]-1,l=i;
}
return ;
}
void exkmp(){
for(int i=1,l=0,r=0;i<=n;i++){
if(i<=r)ex[i]=min(nxt[i-l+1],r-i+1);
while(i+ex[i]<=n&&a[ex[i]+i]==b[ex[i]+1])ex[i]++;
if(i+ex[i]-1>r)l=i,r=i+ex[i]-1;
}
return ;
}
int main(){
scanf("%s%s",a+1,b+1);
n=strlen(a+1),m=strlen(b+1);
getnxt();exkmp();
for(int i=1;i<=m;i++)ans^=1ll*i*(nxt[i]+1);cout<<ans<<endl;//printf("%d ",nxt[i]);puts("");
ans=0;for(int i=1;i<=n;i++)ans^=1ll*i*(ex[i]+1);cout<<ans;
return 0;
}
相当于比较每个后缀的 \(nxt\) 值是否等于后缀长度
由于需要求出现的次数,不妨还是把后缀们平移到前缀的位置
那么发现一个前缀出现的次数是后面前缀出现次数的前缀和
代码实现
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
char a[maxn];
int nxt[maxn],ans,cnt[maxn];
bool vis[maxn];
int main(){
scanf("%s",a+1);
int n=strlen(a+1);
nxt[1]=n;
for(int i=2,l=0,r=0;i<=n;i++){
if(i<=r)nxt[i]=min(nxt[i-l+1],r-i+1);
while(nxt[i]+i<=n&&a[nxt[i]+i]==a[nxt[i]+1])nxt[i]++;
if(nxt[i]+i-1>r)r=nxt[i]+i-1,l=i;
}
for(int i=1;i<=n;i++){
if(i+nxt[i]-1==n)ans++,vis[nxt[i]]=true;
cnt[nxt[i]]++;
}
for(int i=n;i>=1;i--)cnt[i]+=cnt[i+1];
cout<<ans<<endl;
for(int i=1;i<=n;i++)if(vis[i])printf("%d %d\n",i,cnt[i]);
return 0;
}
最新文章
- 1Z0-053 争议题目解析698
- ASP.NET Core 运行原理剖析2:Startup 和 Middleware(中间件)
- STL";源码";剖析-重点知识总结
- HQL查询——select子句
- [OC]宏与const 的使用
- 初学者的python学习笔记2
- ipython又一方便的调试和应用工具!!!
- Spring Collections XML 配置
- ADO.Net 数据库访问技术
- js与C#之间相互调用的一些方法
- keepalived+haproxy-部署高可用负载均衡
- 解决ubuntu下的文本编辑器gedit的乱码问题
- asp.net后台的一些操作
- 注解在android中的使用
- 将 Servlet (HTTP POST/GET)请求发布到OSB
- 引用变量&;和指针*的区别
- jquery获取包含本身的元素
- python的list和tuple
- 拷贝某个区间(copy,copy_back)
- SSM是什么框架?