1、KMP算法
KMP算法(Knuth-Morris-Pratt算法)是一种高效的字符串匹配算法,用于KMP算法(Knuth-Morris-Pratt算法)是一种高效的字符串匹配算法,用于在一个文本串S内查找一个模式串P的出现位置。它的主要思想是利用已知的部分匹配信息,避免在文本串中的多余比较。
KMP算法的核心是计算模式串的最长公共前后缀数组(next数组),然后根据next数组进行匹配。具体步骤如下:
- 初始化两个指针i和j,分别指向模式串和文本串的起始位置。
- 计算模式串的next数组。next[i]表示模式串前i个字符组成的子串的最长公共前后缀的长度。
- 当文本串中当前字符与模式串当前字符相等时,i和j都向右移动一位;否则,i不变,j向右移动一位。
- 如果j等于模式串的长度,说明找到了一个匹配,返回当前位置;否则,继续匹配下一个字符。
- 如果文本串已经遍历完毕,但仍未找到匹配,说明模式串不在文本串。
int* getNext(string str2){ int* Next=new int[str2.length()]; if(str2.length()==0){ return Next; }else if(str2.length()==1){ Next[0]=-1; return Next; }else{ Next[0]=-1; Next[1]=0; int cn=0,i=2; while(i<str2.length()){ if(str2[cn]==str2[i-1]){ Next[i++]=++cn; }else if(cn>0){ cn=Next[cn]; }else{ Next[i++]=0; } } return Next; } } int getTheIndexOf(string str1,string str2){ if(str1.length()==0||str2.length()==0) return -1; int i=0,j=0; int *Next=getNext(str2); while(i<str1.length()&&j<str2.length()){ if(str1[i]==str2[j]){ i++; j++; }else if(Next[j]==-1){ i++; }else{ j=Next[j]; } } return j==str2.length()?i-j:-1; } int main(){ string str1,str2; cin>>str1>>str2; cout<<getTheIndexOf(str1,str2)<<endl; return 0; }
2、MANACHER算法
Manacher算法是一种用于查找一个字符串中所有回文子串位置的线性时间复杂度算法。它的主要思想是将原字符串进行预处理,将每个字符的最长回文半径保存下来,然后利用这些信息来快速找到所有的回文子串。
string extend(string str1){
string ans;
for(int i=0;i<str1.length();i++){
ans+=(str1.substr(i,1)+"#");
}
return ans.substr(0,ans.length()-1);
}
int GetLongestReLength(string str){
if(str.length()==0){
return 0;
}else if(str.length()==1){
return 1;
}else{
string ans=extend(str);
int visited[ans.length()];
for(int i=0;i<ans.length();i++){
visited[i]=0;
}
int c=0; //c表示中点
for(int i=1;i<ans.length();i++){//i扫描到的位置
if(c+visited[c]<i){ //当i在c+visited[c]外,单纯在i点暴力扩
int tmp=0;
for(;i+tmp<ans.length()&&i-tmp>=0&&ans[i+tmp]==ans[i-tmp];tmp++);
visited[i]=tmp-1;
if(visited[i]>=visited[c]){
c=i;
}
}else{ //当i在c+visited[c]内
int anotheri=2*c-i;
if(i+visited[anotheri]<c+visited[c]){
visited[i]=visited[anotheri];
}else if(i+visited[anotheri]>c+visited[c]){
int tmp=0;
for(;i+tmp<ans.length()&&i-tmp>=0&&ans[i+tmp]==ans[i-tmp];tmp++);
visited[i]=tmp-1;
if(visited[i]>=visited[c]){
c=i;
}
}else{
int tmp=visited[anotheri];
for(;i+tmp<ans.length()&&i-tmp>=0&&ans[i+tmp]==ans[i-tmp];tmp++);
visited[i]=tmp-1;
if(visited[i]>=visited[c]){
c=i;
}
}
}
}
int r=visited[c];
for(int i=c+1;i<=c+visited[c];i++){
if(ans[i]=='#') r--;
}
if(ans[c]=='#') return 2*r;
else return 2*r+1;
}
}
int main(){
string str1;
cin>>str1;
cout<<GetLongestReLength(str1)<<endl;
return 0;
}