1. 程式人生 > >【內功】基礎演算法——字串

【內功】基礎演算法——字串

[1] Manacher 

求一個字串中的最長迴文子串。

講解直接放ppt,複習能回憶起來就行。

 

 

 

 

 1 #include <iostream>
 2 #include <string>
 3 #include <vector>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 string manacher(string& s) {
 8     vector<int
> p(s.size(), 0); 9 int mx = 0, dx = 0; 10 for (auto i = 1; i < s.size(); ++i) { 11 if (mx > i) { 12 p[i] = min( p[2*dx-i] , (int)mx-i); 13 } else { 14 p[i] = 1; 15 } 16 while (s[i+p[i]] == s[i-p[i]]) { 17 p[i]++; 18 }
19 if (p[i] + i > mx) { 20 mx = p[i] + i; 21 dx = i; 22 } 23 } 24 int index = -1, max_len = -1; 25 for (auto i = 1; i < s.size(); ++i) { 26 if (p[i] > max_len) { 27 index = i; 28 max_len = p[i]; 29 }
30 } 31 max_len--; // P[i]-1正好是原字串中迴文串的總長度 32 int start = index - max_len; 33 int end = index + max_len; 34 string ans = ""; 35 for (int i = start; i <= end; ++i) { 36 if (s[i] != '#') { 37 ans += s[i]; 38 } 39 } 40 41 cout << "s = "; 42 for (int i = 0; i < s.size(); ++i) { 43 cout << s[i] << " "; 44 } 45 cout << endl; 46 cout << "p = "; 47 for (int i = 0; i < s.size(); ++i) { 48 cout << p[i] << " "; 49 } 50 cout << endl; 51 52 return ans; 53 } 54 55 int main() { 56 string s; 57 cin >> s; 58 string tmp = "$#"; 59 for(int i = 0; i < s.size(); ++i) { 60 tmp += s[i]; 61 tmp += "#"; 62 } 63 cout << tmp << endl; 64 string palindrome = manacher(tmp); 65 cout << palindrome << endl; 66 return 0; 67 }
manacher

 

[2] KMP

判斷在字串 s 中查詢 模式串 p,返回 p 在 s 中第一個位置下標。

演算法講解我看了 July 的 《程式設計之法》4.4 字串的查詢,不管這個人優秀不優秀,我只看我認為能讓我學到東西的文章。

https://blog.csdn.net/v_JULY_v/article/details/7041827

他講了一個要點,就是next陣列的含義,next 陣列就是隻要將各個字首和字尾的公共元素的最大長度值右移一位,並且把初值賦值成 -1 即可。

 

基礎題目練習:https://hihocoder.com/problemset/problem/1015

題意是找出 S 串中出現模式串 P 的個數。