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\n", ans);
    return 0;
}
View Code

 

posted @ 2017-09-20 23:11  19992147  阅读(138)  评论(0编辑  收藏  举报