zoukankan      html  css  js  c++  java
  • Codeforces 17E Palisection

    题目传送门

      传送点I

      传送点II

      传送点III

    题目大意

      给定一个串$s$询问,有多少对回文子串有交。

      好像很简单的样子。

      考虑能不能直接求,感觉有点麻烦。因为要考虑右端点在当前回文子串内还有区间包含问题。

      那么考虑补集转化。问题转化成,考虑当前的回文串,之前有多少个回文串与它不相交。

      跑一遍Manacher。然后先差分再二阶前缀和求出以第$i$个位置为右端点的回文子串的个数。然后再求一次前缀和就可以了。

      然后再扫一遍就做完了。

    Code

     1 /**
     2  * Codeforces
     3  * Problem#17E
     4  * Accepted
     5  * Time: 186ms
     6  * Memory: 37200k
     7  */
     8 #include <bits/stdc++.h>
     9 using namespace std;
    10 typedef bool boolean;
    11 
    12 const int N = 2e6 + 5, M = 51123987, inv2 = (M + 1) >> 1;
    13 
    14 int add(int a, int b) {
    15     return ((a += b) >= M) ? (a - M) : (a);
    16 }
    17 
    18 int sub(int a, int b){
    19     return ((a -= b) < 0) ? (a + M) : (a);
    20 }
    21 
    22 int n, m;
    23 char s[N], str[N << 1];
    24 int mxr[N << 1];
    25 int f[N];
    26 
    27 inline void init() {
    28     scanf("%d", &n);
    29     scanf("%s", s + 1);
    30 }
    31 
    32 void Manacher() {
    33     int R = 0, cen = 0;
    34     str[0] = '+';
    35     for (int i = 1; i <= n; i++) {
    36         str[++m] = s[i];
    37         if (i != n)
    38             str[++m] = '#';
    39     }
    40     str[++m] = '-';
    41     
    42     for (int i = 1; i < m; i++) {
    43         if (i < R)
    44             mxr[i] = min(R - i, mxr[(cen << 1) - i]);
    45         while (str[i - mxr[i]] == str[i + mxr[i]])
    46             mxr[i]++;
    47         if (i + mxr[i] > R)
    48             R = i + mxr[i], cen = i;
    49     }
    50 }
    51 
    52 inline void solve() {
    53     Manacher();
    54     for (int i = 1; i < m; i++)
    55         f[(i >> 1) + 1]++, f[((i + mxr[i]) >> 1) + 1]--;
    56     for (int i = 2; i <= n; i++)
    57         f[i] = add(f[i], f[i - 1]);
    58     for (int i = 2; i <= n; i++)
    59         f[i] = add(f[i], f[i - 1]);
    60     int res = sub((f[n] * 1ll * f[n]) % M, f[n]) * 1ll * inv2 % M;
    61     for (int i = 2; i <= n; i++)
    62         f[i] = add(f[i], f[i - 1]);
    63     f[0] = 0, f[n + 1] = 0;
    64     
    65     for (int i = 1; i <= n; i++) {
    66         res = sub(res, sub(f[i - 1], f[max(i - ((mxr[(i - 1) << 1 | 1] + 1) >> 1) - 1, 0)]));
    67         if (i < n)
    68             res = sub(res, sub(f[i - 1], f[max(i - (mxr[i << 1] >> 1) - 1, 0)]));
    69     }
    70     printf("%d
    ", res);
    71 }
    72 
    73 int main() {
    74     init();
    75     solve();
    76     return 0;
    77 }
  • 相关阅读:
    安装和使用Glassfish
    3GP 的 DASH设计原则与标准
    hdu 2686 Matrix 最小费用最大流 或 多线程DP
    [Win32]客户端程序
    二叉查找树中节点的删除。
    Android:获取屏幕完整宽高,包含状态栏
    Django学习总结之五模型
    畸形的从业观
    调试版本和发行版本
    jsp中常见的错误处理(未完待续)
  • 原文地址:https://www.cnblogs.com/yyf0309/p/9769845.html
Copyright © 2011-2022 走看看