Loading

I - Skr 【18南京网络赛】

I - Skr

求一个长度 2e6 的数字串的所有不同回文串的和,对 1000,000,007 取模

显然的回文树板子题,要搞个快速幂才行

/*
 * @Author: zhl
 * @LastEditTime: 2020-12-01 10:32:02
 */
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;

const int N = 2e6 + 10, mod = 1e9 + 7;
ll ans;
struct Node {
	int ch[10], fail;
	int len, sum;
	ll val;
}tr[N];

char s[N];
int last, tot = 2;

int newnode(int len) {
	tr[tot].len = len;
	//tr[tot].fail = 0;
	//for(int i = 0;i < 26;i++)tr[tot].ch[i] = 0;
	return tot++;
}
int getFail(int x, int pos) {
	while (s[pos - tr[x].len - 1] != s[pos]) x = tr[x].fail;
	return x;
}

void init() {
	tr[0].len = 0, tr[1].len = -1;
	tr[0].fail = 1; tr[1].fail = 0;
	last = 0;
}
ll qpow(ll a, ll p) {
	ll ans = 1;
	while (p) {
		if (p & 1)ans = (ans * a) % mod;
		a = (a * a) % mod;
		p >>= 1;
	}
	return ans;
}
void insert(int pos) {
	int cur = getFail(last, pos);
	int c = s[pos] - '0';
	if (tr[cur].ch[c] == 0) {
		// 出现了新的本质不同的回文串
		int now = newnode(tr[cur].len + 2);
		tr[now].fail = tr[getFail(tr[cur].fail, pos)].ch[c]; //fail指向后缀中的最长回文串
		tr[now].sum = tr[tr[now].fail].sum + 1;
		tr[cur].ch[c] = now;
		ll pre = tr[cur].val;
		ll res = c;
		if (tr[cur].len == -1)res = 0;
		else res = (res * qpow(10, tr[cur].len + 1));
		res = (res + c) % mod;
		res = (res + pre * 10 % mod) % mod;
		tr[now].val = res; ans = (ans + res) % mod;
	}
	last = tr[cur].ch[c];
}

int main() {
	scanf("%s", s + 1);
	int k = 0; int n = strlen(s + 1);
	init();
	for (int i = 1; i <= n; i++) {
		insert(i);
	}
	printf("%lld\n", ans);
}
posted @ 2020-12-01 21:42  —O0oO-  阅读(65)  评论(0编辑  收藏  举报