標簽:int 子串 second line alt strlen inf == 根據
就是一個\(O(n)\)的複雜度求解最長回文子串的算法
思路的話我隨便說下
首先回文串可能是奇数也可能是偶数,那麽对称中心就有可能是两个字符的空隙,所以先给每个字符插如一个隔板符号 ‘|‘ 第0个字符插入‘~‘ 防止出现超出边界的问题
如abcbs -> ~|a|b|c|b|s|
設\(p[i]\)以\(i\)爲中點的回文半徑包括自己本身
例如|a|b|a|
那麽\(p[4]=4\)
我们也维护一个$ mx$ 和 \(id\),表示對于當前計算的\([1,i-1]\)中,\(i + p[i]\) 的最大值是$ mx\(,\)mx \(對應的\) i \(記爲\)id$
当你现在开始计算 p[i] 时,默认$ p[1..i-1] $都已经算出。如果 \(mx > i\),那麽根據对称得出
\(p[i] >= min(p[2 \times id - i], mx - i+1)\)
由下圖可以看出
而最後的答案即爲\(max(p[i])-1\)
很多人都沒有解釋爲什麽,其實很簡單
根據\(p[i]\)的定义,那麽扩展的回文串的长度即为\(2p[i]-1\)
而其中#
占\(p[i]\)個,所以原回文串的長度即爲\(p[i]-1\)
這個算法挺簡單的,感覺比kmp都要簡單很多
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
//typedef pair<int,int> pii;
#define fi first
#define se second
#define debug printf("aaaaaaaaaaa\n");
const int maxn=2e7+5,inf=0x3f3f3f3f,mod=998244353;
const ll INF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-7;
char temp[maxn];
char s[maxn];
int p[maxn];
int main(){
scanf("%s",temp+1);
int n=strlen(temp+1);
n=2*n+1;
s[0]=‘~‘;
for(int i=1;i<=n;i++){
if(i%2){
s[i]=‘|‘;
}else{
s[i]=temp[i/2];
}
}
int mx=0,id=1,ans=0;
for(int i=1;i<=n;i++){
p[i]=min(p[2*id-i],mx-i+1);
while(s[i+p[i]]==s[i-p[i]]) p[i]++;
if(p[i]+i-1>=mx){
mx=p[i]+i-1;
id=i;
ans=max(ans,p[i]-1);
}
}
printf("%d\n",ans);
return 0;
}
標簽:int 子串 second line alt strlen inf == 根據
原文地址:https://www.cnblogs.com/hunxuewangzi/p/15068080.html