1. 程式人生 > 其它 >2.HTML 基礎知識學習

2.HTML 基礎知識學習

647. 迴文子串 - 力扣(LeetCode) (leetcode-cn.com)

方法1:中心擴充套件--遍歷中心/遍歷中心種類

  假設字串長度n=4。

 

  迴文左起始位置 迴文右起始位置
0 0 0
1 0 1
2 1 1
3 1 2
4 2 2
5 2 3
6 3 3

可以看出中心種類有7中,可得公式s=2*n-1,程式碼如下;

public int countSubstrings(String s) {         int n = s.length(), ans = 0;         for (int i = 0; i <=2*n-1; ++i) {             int l = i / 2, r = i / 2 + i % 2;             while (l >= 0 && r < n && s.charAt(l) == s.charAt(r)) {                 --l;                 ++r;                 ++ans;             }         }         return ans;     }

方法2:manacher演算法

public int countSubstrings(String s) {
  int n = s.length();
  StringBuffer t = new StringBuffer("$#");
  for (int i = 0; i < n; ++i) {
    t.append(s.charAt(i));
    t.append('#');
  }
  n = t.length();
  t.append('!');//第一個與最後一個字元不同,中心擴充套件時無需判斷邊界可安全退出

  int[] f = new int[n];
  int iMax = 0, rMax = 0, ans = 0;
  for (int i = 1; i < n; ++i) {
    // 初始化 f[i]
    f[i] = i <= rMax ? Math.min(rMax - i + 1, f[2 * iMax - i]) : 1;//rMax-i+1防止f[2*iMax-i]過大超過右邊界
    // 中心拓展
    while (t.charAt(i + f[i]) == t.charAt(i - f[i])) {
      ++f[i];
    }
    // 動態維護 iMax 和 rMax
    if (i + f[i] - 1 > rMax) {
      iMax = i;
      rMax = i + f[i] - 1;
    }
    // 向上取整,f[i]初始為1,所以除二即可
    ans += f[i] / 2;
  }

  return ans;
}

時間複雜度:O(n))。即 Manacher 演算法的時間複雜度,由於最大回文右端點 r_mrm只會增加而不會減少,故中心拓展進行的次數最多為 O(n)O(n),此外我們只會遍歷字串一次,故總複雜度為 O(n)O(n)。

空間複雜度:O(n)。