zoukankan      html  css  js  c++  java
  • bzoj3160

    fft+manacher

    fft都快忘了。。。

    其实我们发现,这个问题是可以用fft做的,因为是回文子序列,所以我们直接自己和自己求卷积,然后扫描每个位置,注意是每个位置,因为包括奇数长度和偶数长度,f[i]为第i个位置上的对称字符的数量,那么一共就有(2^f[i])-1个回文子序列,因为是要不连续的,所以用manacher求出连续的就行了

     
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 400010, mod = 1000000007;
    const double pi = acos(-1);
    int n, m, pos, mx, len, L;
    complex<double> a[N], b[N];
    int r[N], p[N], f[N];
    ll pw[N];
    ll ans;
    char s[N], t[N];
    void fft(complex<double> *a, int f)
    {
        for(int i = 0; i < n; ++i) if(i < r[i]) swap(a[i], a[r[i]]);
        for(int i = 1; i < n; i <<= 1)
        {
            complex<double> t(cos(pi / i), f * sin(pi / i));
            for(int p = i << 1, j = 0; j < n; j += p)
            {
                complex<double> w(1, 0);
                for(int k = 0; k < i; ++k, w *= t)
                {
                    complex<double> x = a[j + k], y = w * a[j + k + i];
                    a[j + k] = x + y;
                    a[j + k + i] = x - y; 
                }
            }
        }   
    }
    int main()
    {
        scanf("%s", t);
        n = strlen(t);
        s[0] = '-';
        s[len = 1] = '#';
        for(int i = 0; i < n; ++i) s[++len] = t[i], s[++len] = '#';
        for(int i = 1; i <= len; ++i)
        {
            if(mx > i) p[i] = min(mx - i, p[2 * pos - i]);
            while(s[i + p[i]] == s[i - p[i]]) ++p[i];
            if(i + p[i] > mx)
            {
                pos = i;
                mx = i + p[i];
            }
            ans -= p[i] >> 1;
        } 
        len = n;
        m = 2 * n;
        for(n = 1; n <= m; n <<= 1) ++L;
        for(int i = 0; i < n; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (L - 1));
        for(int i = 0; i < len; ++i) a[i] = (t[i] == 'a' ? 1 : 0), b[i] = (t[i] == 'b' ? 1 : 0);
        fft(a, 1);
        fft(b, 1);
        for(int i = 0; i < n; ++i) a[i] *= a[i], b[i] *= b[i];
        fft(a, -1);
        fft(b, -1);
        pw[0] = 1ll;
        for(int i = 1; i <= n; ++i) pw[i] = (pw[i - 1] << 1ll) % mod;
        for(int i = 0; i < m - 1; ++i) 
        {
            int x = (int)(a[i].real() / n + 0.5), y = (int)(b[i].real() / n + 0.5);
            ans = (ans + pw[(x + y + 1) >> 1] - 1) % mod;
        }   
        printf("%lld
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    mongodb 条件查询
    node 创建静态web服务器(下)(处理异步获取数据的两种方式)
    node 创建静态web服务器(上)
    node.js 从文件流中读写数据及管道流
    node.js 中的 fs (文件)模块
    vue-router 嵌套路由
    (转载)js调用打印机 打印整体或部分
    web react面试题
    vue 面试题
    vue 父页面中含子页面滑动,滑动结束,底部组件进行滑动
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7565593.html
Copyright © 2011-2022 走看看