zoukankan      html  css  js  c++  java
  • 2020.2.26考试T2 三元组

    首先我们正着对每一个 (j) 求一边 (displaystyle sum i),设为 (a[j])

    类似的倒着对每个 (j) 求一边 (displaystyle sum k),设为 (b[j])

    那么答案就是 (displaystyle sum a[i] imes b[i+1])

    考虑如何求 (a) 我们在建立回文自动机的时候统计一下以 (j) 为结尾的回文串的个数 (num) 以及回文串的长度和 (sum), 则 (a[j]=(i+1) imes num -sum)

    倒着也同理

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define LL long long
    using namespace std;
    int T, n;
    LL ans;
    const int N = 1000010, mod = 1e9 + 7;
    int a[N], b[N];
    char s[N];
    struct PAM
    {
    	int em, last, cnt, now;
    	int tr[N][26], len[N], fail[N], sum[N], num[N];
    	void YYCH()
    	{
    		for (int i = 0; i <= cnt; ++i)
    		{
    			len[i] = num[i] = fail[i] = sum[i] = 0;
    			for (int j = 0; j < 26; ++j)tr[i][j] = 0;
    		}
    		fail[0] = 1; fail[1] = 0; len[0] = 0; len[1] = -1; cnt = 1; last = 0;
    	}
    	int getfail(int x)
    	{
    		if (now == 1)while (s[em - len[x] - 1] != s[em])x = fail[x];
    		else while (s[em + len[x] + 1] != s[em])x = fail[x];
    		return x;
    	}
    	void Insert(int x)
    	{
    		int f1 = getfail(last);
    		if (!tr[f1][x])
    		{
    			len[++cnt] = len[f1] + 2;
    			fail[cnt] = tr[getfail(fail[f1])][x];
    			num[cnt] = num[fail[cnt]] + 1;
    			sum[cnt] = sum[fail[cnt]] + len[cnt]; sum[cnt] %= mod;
    			tr[f1][x] = cnt;
    		}
    		last = tr[f1][x];
    	}
    } P;
    int main()
    {
    	freopen("triple.in", "r", stdin);
    	freopen("triple.out", "w", stdout);
    	cin >> T;
    	while (T--)
    	{
    		scanf("%s", s + 1); n = strlen(s + 1); ans = 0;
    		P.YYCH(); P.now = 1;
    		for (int i = 1; i <= n; ++i)
    		{
    			P.em = i; P.Insert(s[i] - 'a');
    			a[i] = ((LL)(i + 1) * P.num[P.last] - P.sum[P.last]) % mod;
    		}
    		P.YYCH(); P.now = 2;
    		for (int i = n; i >= 1; --i)
    		{
    			P.em = i; P.Insert(s[i] - 'a');
    			b[i] = ((LL)(i - 1) * P.num[P.last] + P.sum[P.last]) % mod;
    		}
    		for (int i = 1; i < n; ++i)(ans += (LL)a[i] * b[i + 1]) %= mod;
    		cout << (ans % mod + mod) % mod << '
    ';
    	}
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    Java
    Java
    Java
    Java
    运算问题
    Idea常用快捷键
    java变量和变量命名规范
    java常用数据类型和基本数据类型转换和进制和大数运算
    java注释和标识符规范
    使用命令行生成的第一个java程序
  • 原文地址:https://www.cnblogs.com/wljss/p/12628908.html
Copyright © 2011-2022 走看看