那些造过几遍的轮子

判断字符串的偶数回文子串。

思路是哈希前缀和和后缀和,配合二分进行求解。

#include<iostream>
#include<algorithm>

using namespace std;

const int N = 5e5 + 5;

int n;
string s;

long long base = 131, mod = 13331;
long long qpow(long long u, int v) {
  long long ans = 1;
  while (v) {
    if (v & 1) ans = (ans * u) % mod;
    u = (u * u) % mod;
    v >>= 1;
  }
  return ans;
}
long long inv = qpow(base, mod - 2);
long long pre[N], suf[N];

bool chk(int x, int i) {qii
  long long l = pre[i] - (pre[i - x] * qpow(base, x));
  long long r = suf[i + 1] - (suf[i + 1 + x] * qpow(base, x));
  l = ((l % mod) + mod) % mod;
  r = ((r % mod) + mod) % mod;
  int L = i - x, R = i + 1 + x;haxi
  return l == r;
}

void solve() {
  cin >> n >> s;
  s = ' ' + s;
  cout << s << endl;
  for (int i = 1; i <= n; ++i) {
    pre[i] = (pre[i - 1] * base) % mod;
    pre[i] = (pre[i] + (s[i] - 'a')) % mod;
  }
  for (int i = n; i >= 1; --i) {
    suf[i] = (suf[i + 1] * base) % mod;
    suf[i] = (suf[i] + (s[i] - 'a')) % mod;
  }
  for (int i = 1; i < n; ++i) {
    int l = 0, r = min(i, n - i);
    while (l < r) {
      int mid = (l + r + 1) >> 1;
      if (chk(mid, i) == true) l = mid;
      else r = mid - 1;
    }
    cout << i << " : " << l << endl;
  }
}

signed main() {
  freopen("text.in", "r", stdin);
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);

  int T;cin >> T;
  while (T--) solve();

  return 0;
}

posted @ 2023-06-25 17:32  _maze  阅读(17)  评论(0编辑  收藏  举报