首页 > 其他分享 >KMP与Trie

KMP与Trie

时间:2023-08-03 17:38:05浏览次数:30  
标签:nxt 前缀 Trie printf tree ++ int KMP

KMP算法

KMP算法用于解决字串与母串的匹配问题,可看作哈希的简单写法,时间复杂度O(m+n)

KMP算法的核心优势在于相对于暴力枚举,它可以省去重复的步骤,从而将匹配过程由O(mn)优化为近似O(2m),该算法的核心在于寻找子串前缀与后缀重合的最大长度,也就是next数组,那么怎么求呢?就是将子串自匹配

代码如下:

cin >> (a+1);
l = strlen(a+1);
for(int i = 2,j = 0;i <= l;i++){
while(j && a[i] != a[j+1]) j = nxt[j];
if(a[i] == a[j+1]) j++;
nxt[i] = j;
}

那么KMP算法的具体用法有哪些呢?大致分为三种

一、       求最小循环节

例如:我们在abababab中,找到其前后缀重复的最大长度,也就是next[8],此时其值为6,不难发现s1-6 = s3-8,s1-2 = s7-8,由此可推出其最小循环节长度为二,也就是L-next[L];

二、       求一个字符串是由多少个相同字符串重复组成的

分为两种情况:可重复的:直接用总长度除以最小循环节

int k = l-nxt[l];
if(l%k) printf("1\n");
else printf("%d\n",l/k);

不可重复的:子母串正常匹配,然后匹配到答案++,j归零

for(int i = 1,j = 0;i <= lb;i++){
while(j && b[i] != a[j+1]) j = nxt[j];
if(b[i] == a[j+1]) j++;
if(j == la) ans++,j = 0;
}
printf("%d\n",ans);

三、       题面如下

串是有限个小写字符的序列,特别的,一个空序列也可以是一个串。一个串 P 是串 A 的前缀,当且仅当存在串 B,使得 A=PB。如果P≠A并且 P 不是一个空串,那么我们说 P 是 A 的一个 proper 前缀。

定义 Q 是 A 的周期,当且仅当 Q 是 A 的一个 proper 前缀并且 A 是 QQ 的前缀(不一定要是 proper 前缀)。比如串 abab 和 ababab 都是串 abababa 的周期。串 A 的最大周期就是它最长的一个周期或者是一个空串(当 A 没有周期的时候),比如说,ababab 的最大周期是 abab。串 abc 的最大周期是空串。

给出一个串,求出它所有前缀的最大周期长度之和。

思路:求出最小next数组,用总长度减去即是答案

原因:next数组定义为前后缀重合最大长度,那么以这个长度切开再扩倍一定是可以前后相接的,代码:

#include<bits/stdc++.h>
using namespace std;
char a[1000005];
int n,la,lb,nxt[1000005];
long long ans;
int main(){
scanf("%d",&n);
cin >> (a+1);
for(int i = 2,j = 0;i <= n;i++){
while(j && a[i] != a[j+1]) j = nxt[j];
if(a[i] == a[j+1]) j++;
nxt[i] = j;
}
int q;
for(int i = 1;i <= n;i++){
q = i;
while(nxt[q]) q = nxt[q];
if(nxt[i]) nxt[i] = q;
ans+=i-q;
}
printf("%lld",ans);
return 0;
}

Trie字典树

解决多串前缀匹配问题

核心:有点更新指针,继续走,无点建点,一个串走完需标记

模板

#include<bits/stdc++.h>
using namespace std;
int t,n,tree[100005][15],idx,mk[100005],q,l;
string a;
bool insert(string s){
int c,p = 0,flag = 0;
for(int i = 0;i < l;i++){
c = s[i] - '0';
if(!tree[p][c]){
tree[p][c] = ++idx;
p = tree[p][c];
}else{
p = tree[p][c];
if(mk[p]||i == l-1) flag = 1;
}
}
mk[idx]++;
return flag;
}
int main(){
scanf("%d",&t);
for(int i = 1;i <= t;i++){
scanf("%d",&n);
q = 0;
idx = 0;
memset(tree,0,sizeof(tree));
memset(mk,0,sizeof(mk));
for(int j = 1;j <= n;j++){
cin >> a;
l = a.size();
if(insert(a)){
q = 1;
}
}
if(!q) printf("YES\n");
else printf("NO\n");
}
return 0;
}

注意p和idx初始值要相同,不然会出问题

标签:nxt,前缀,Trie,printf,tree,++,int,KMP
From: https://www.cnblogs.com/breeze-zyh/p/17603919.html

相关文章

  • LeetCode 周赛上分之旅 # 36 KMP 字符串匹配殊途同归
    ⭐️本文已收录到AndroidFamily,技术和职场问题,请关注公众号[彭旭锐]和BaguTreePro知识星球提问。学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越抽象,它能覆盖的问题域就越广,理解难度也更复杂。在这个专栏里,小彭与你分享每场LeetCode周赛的解题报告,一......
  • 笔记:KMP的复习
    Record一个重要的字符串算法,这是第三次复习。通过总结我认为之所以某个算法总是忘记,是因为大脑始终没有认可这种算法的逻辑(也就是脑回路)。本篇主要讲解从KMP的应用场景,再到算法知识,以及例题。Main现有两个字符串\(A,B\),求出\(A\)在\(B\)中出现的次数。范围:字符串长度......
  • P3375 【模板】KMP 字符串匹配 题解
    前言狗屁不是,建议别看!!! 题目链接P3375【模板】KMP字符串匹配-洛谷|计算机科学教育新生态(luogu.com.cn) 分析先给个例子s1:ABCABCABBs2:ABCABB若使用朴素算法匹配,当匹配到s1:ABCABCABBs2:ABCABB时,朴素算法会跳出,然后匹配下一位。最终匹配到s1:ABCABCABBs2:......
  • c++字符串搜索之KMP
    classSolution{private:voidgetNext(int*arr,stringstr){intlen=str.length();arr[0]=0;intj=0;for(inti=1;i<len;i++){while(j>0&&str[i]!=str[j]){......
  • 链表/栈/队列/KMP
    链表用数组模拟,不同于结构体加指针调用new关键字开上万级别的节点非常慢,基本会超时单链表来构造邻接表用于存图与树基本结构:head表示头结点的下标e[i]表示节点i的值ne[i]表示节点i的下一个节点的下标idx存储当前已经用到了哪个节点,表示新节点基本操作:......
  • celery 启动显示警告信息“...whether broker connection retries are made during st
    博客地址:https://www.cnblogs.com/zylyehuo/在settings文件中设置broker_connection_retry_on_startup=True修改配置后运行效果如下......
  • kmp算法的个人理解
    最长前后缀:假设有一段字符串:"aabaa"则这段字符串的前缀有:aaaaabaaba后缀:aaabaaabaa求最长公共前后缀的方法:找到前缀和后缀中相同的字符串:aaa其中最长的字符串为aa则"aabaa"这个字符串的最长公共前后缀为aaaa其长度为2按照以上的方式逐个计算"aabaa"中的每个子字符串得到......
  • Introduction to Embedding for Retrieval 向量化召回简介
    引言搜广推类似场景都是retrieval+ranking两阶段方式,前者用从海量候选粗选一轮,后者再用负载模型,是效果、延迟和机器资源的trade-off的产物。retrieval广泛使用embedding+ANN方案,比起invertindex个性化更强。embedding动机,word2vec用向量表示高维的one-hot编码,向量的距......
  • kmp与最小循环节
    #include<iostream>#include<string.h>#include<vector>usingnamespacestd;constintN=1e6+10,INF=0x3f3f3f3f;chars2[N];intd[N];//d[i]表示以i结尾的字符串中最大公共前后缀的长度voidinit()//得到模式串的d[]下标是从0开始的{intlen=strlen(s2);......
  • Qt Cannot retrieve debugging output报错 (无法获取调试输出.)
    我们在QT中有时会遇到Cannotretrievedebuggingoutput报错,无法利用qDebug输出内容,原因是开了两个qt软件,这是需要我们把其中一个qt软件关了,然后在唯一的qt中打开项目,放心,一个窗口仍然可以运行两个程序。 ......