最長回文串演算法

2021-12-29 23:38:23 字數 2479 閱讀 3411

給定乙個字串找出最長回文字串範圍,例如abaabac,最長回文為abaaba

1、使用暴力的演算法需要o(n^3)的複雜度,需要o(n^2)的複雜度去運算字串所用的子串,然後使用o(n)去判斷是否是回文串,從而定位最長的回文子串。

[cpp]  

int lps_bl(char str, int len)  

int i, j;  

int start, end, max_lps;  

for(i = 0; i < len; i++)  

if(start >= end)  

}  }  

}  printf("lps_bl:%d\n", max_lps);  

return max_lps;  

}   

可以看到這種演算法很容易理解,只是o(n^3)的複雜度相對比較高。

2、使用動態規劃的思想進行求解,思路是利用子串從短到長進行逐步的動態規劃求解,可以理解為從中心向兩邊擴散,如果乙個字串的子串是回文串,那麼就可以儲存這個狀態,然後從短向長蔓延進行計算:

當i == j 時 肯定是長度為1 的回文串,dp[i][j] = 1

當dp[i][j] == 1 時如果s[i-1] == s[j+1], dp[i][j] == 1,(如果子串是回文串,並且首尾相同,那麼當前的子串也是回文串)

當i+1 == j 時,s[i] == s[j], 那麼dp[i][j] == 1,這個狀態值在計算時會有些特殊,因為 j = i +1,那麼i-1和j+1會與i和j的值相反,但是不影響整體的計算。

[cpp] 

#include  

#include  

#include  

int lps_dp(char str, int len)  

int dp[100][100] = ;  

int i,j, m;  

for(i = 0; i < 100; i++)  

int start = 0;  

int end = 0;  

int max_lps = 0;  

char buf[100] = ;  

//printf("len:%d\n", len);  

for(m = 1; m < len; m++)  

}else if(dp[i+1][j-1] == 1 && str[i] == str[j])  

}  }  

}  //memcpy(buf, str+start, max_lps);  

//buf[max_lps] = '\0';  

//printf("max_len:%d\tlps:%s\n", max_lps, buf);  

return max_lps;  

}   

3、受以上動態規劃演算法的啟發,可以考慮選取中間點,然後逐步向兩邊蔓延的策略進行回文串的判斷,這種方法相對於動態規劃的演算法更容易理解,而且空間複雜度會由o(n^2)變為o(1)

[cpp]  

int lps_ext(char str, int len)  

int i;  

int max_lps = 1;  

int start = 0;  

char buf[100] = ;  

for(i = 1; i < len; i++)  

low--;  

high++;  

}  low = i - 1;  

high = i + 1;  

while(low >= 0 && high < len && str[low] == str[high])  

low--;  

high++;  

}  }  

memcpy(buf, str + start, max_lps);  

printf("%d\tlps_ext:%s\n",max_lps, buf);  

return max_lps;  

}  下面介紹一種o(n)的演算法:manacher, 這個演算法開始理解起來比較複雜,但確實有一定的技巧性,第乙個技巧是將可能的回文串,無論是奇數個字元還是偶數個字元全部變為奇數,這樣有利於利用對稱性特徵進行計算,變換方式如下:

在每個字元的兩邊都插入乙個特殊的符號。比如 abba 變成 #a#b#b#a#, aba變成 #a#b#a#。 為了進一步減少編碼的複雜度,可以在字串的開始加入另乙個特殊字元,這樣就不用特殊處理越界問題,比如$#a#b#a#。

下面以字串12212321為例,經過上一步,變成了 s = "$#1#2#2#1#2#3#2#1#";

演算法引入兩個變數id和mx,id表示最長回文子串的中心位置,mx表示最長回文字串的邊界位置,即:mx=id+p[id]。

在這裡有乙個非常有用而且神奇的結論:如果mx > i,那麼p[i] >= min(p[2 * id - i], mx - i) 分開理解就是:

如果mx - i > p[j], 則p[i]=p[j]

否則,p[i]  = mx - i.

最長回文串演算法

總的來說,最長回文串演算法分為以下幾種。通過遍歷整個字串來說實現對最長回文串的查詢 首先乙個字串所有子串,個數為n2個,然後逐個判斷遍歷即可,演算法複雜度o n3 如下 def is palindrome s str length len s for i in range str length 2 ...

最長回文串 演算法 4 求解最長回文子串

問題描述 給定乙個字串 s,找到 s 中最長的回文子串。你可以假設 s 的最大長度為 1000。注釋 回文通俗的說就是正著念和反著念都一樣,如 上海自來水來自海上。示例 1 輸入 dabccbac 輸出 abccba 示例 2 輸入 cbbd 輸出 bb 解題思路 此處撰寫解題思路 遍歷每乙個索引,...

Manacher最長回文串演算法

在介紹演算法之前,首先介紹一下什麼是回文串,所謂回文串,簡單來說就是正著讀和反著讀都是一樣的字串,比如abba,noon等等,乙個字串的最長回文子串即為這個字串的子串中,是回文串的最長的那個。一.通常解決的問題 給定乙個字串,求出其最長回文子串。例如 1 s abcd 最長回文長度為 1 2 s a...