·字符串哈希
那很暴力了
关于哈希的介绍这里复制粘贴了:
·KMP算法
时间复杂度 O(nm) -> O(n+m)
学过了就简单说一下吧,本质上就是求前后缀,目的是更快的往后遍历(右移更快一些并且不用跳回来再次遍历)
首先是比较难的pmt前后缀数组,这里给一下模板代码
模板
void PMT(string s){
ll j=0,n=s.size();
af(i,1,n-1){
while(j&&s[i]!=s[j]) j=pmt[j-1];
if(s[i]==s[j]) j++;
pmt[i]=j;
}
}
void KMP(string s1,string s2){
ll j=0;
af(i,0,s1.size()-1){
while(j&&s1[i]!=s2[j]) j=pmt[j-1];
if(s1[i]==s2[j]) j++;
if(j==s2.size()){
j=pmt[j-1];
}
}
}
·Manacher算法
时间复杂度 O(n^2) -> O(n)
主要步骤:
-
预处理:在原字符串的每个字符间插入一个特殊字符(如'#'),将奇数和偶数长度的回文统一处理为奇数长度。
-
维护变量:
-
P[i]:记录以i为中心的最长回文半径 -
C:当前回文中心 -
R:当前回文右边界
-
-
算法流程:
遍历字符串,对于每个位置i:-
如果i在R内,镜像解决,可以利用对称性快速获取P[i]的初始值
-
暴力更新向两边扩展以确定P[i]的准确值
-
如果i+P[i]超过R,继续暴力更新,更新C和R
-
·最小表示法
也就是找字符串的最小表示(好像说了跟没说一样)
最小表示法是一种用于找到字符串或序列的“最小表示”的算法。它主要用于处理循环同构的字符串,找到其中字典序最小的那个。例如,字符串 bcda 的表示有 bcda, cdab, dabc, abcd,其中 abcd是字典序最小的表示。
通过双指针i和j来确定字符串的字典序
给一下模板
模板
n=read();
af(i,0,n-1) a[i]=read();
ll i=0,j=1,k=0;
while(i<=n&&j<=n&&k<=n){
if(a[(i+k)%n]>a[(j+k)%n]) i=i+k+1,k=0;
if(a[(i+k)%n]<a[(j+k)%n]) j=j+k+1,k=0;
if(a[(i+k)%n]==a[(j+k)%n]) k++; if(i==j) i++;
}
ll ans=min(i,j);
af(p,0,n-1) cout<<a[(p+ans)%n]<<' ';
比较过程:
情况1:s[i+k] == s[j+k]
k++
情况2:s[i+k] > s[j+k]
i = i + k + 1
情况3:s[i+k] < s[j+k]
j = j + k + 1
终止条件:i 或 j 超出字符串长度
题目的话回来再说吧(绝对不是我没写完)






