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
", ans);
}