Z函数与扩展KMP算法详解 - 以CF126B为例
Z函数——拓展KMP
算法作用:(考虑1base)求文本串 T 的每一个后缀与模式串 M 的最长公共前缀长度。核心数组z[i]就表示
模板:
1.传的是0base串,函数内部会处理。
2.其次一般来说前面是模式串,间隔一个$分隔符后是文本串。这样就是可以知道文本串中出现了多少次模式串。
z函数的求解:
1 | vector<int> exkmp(string s){ |
如何达到kmp的匹配作用(无关border)
1 | void solve() |
例题1:给定字符串S,求最长子串T满足:T是S的前缀又是 𝑆的后缀同时又在 𝑆中间出现过。Password - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
Sol:如何用exkmp解决?考虑首先需要满足lcp长度是正好能到后缀的,这用z函数很好约束。考虑怎么处理在中间出现过这个问题?考虑维护最大z[i]值为x,对于当前这个位置的z[i],满足x<=z[i]即可,这是由于z[i]具有二段性。
1 | void solve() |
bonus:如何用kmp解决?
答案一定是某个前缀,我们只需要知道长度就可以了。由于是前缀也是后缀,所以考虑border。而不难画图发现答案一定为nx[nx[n]]或者nx[n]。按长度从大到小依次判断出现次数即可。
void solve(){
string s;
cin>>s;
KMP kmp(s);
auto v=kmp.getnxt();
int n=s.size();
s=" "+s;
map<int,int>mp;
for(int i=1;i<=n;i++){
mp[v[i]]++;
}
int len=0;
if(mp[v[n]]>=2)len=v[n];
else len=v[v[n]];
if(len)cout<<s.substr(1,len)<<endl;
else cout<<"Just a legend"<<endl;
}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 爱飞鱼的blog!
