题解
题目大意 给你一个数字串 问这个串的所有子段中是回文串且不重复的值相加的和 结果模1e9+7
使用回文树模版 回文树可以统计有多少个不相同的字符串 在创建新节点的时候说明出现了一个新的不重复的回文 将每个新节点的值加入答案
新节点的值等于当前节点数字*pow(10, 当前节点长度-1) + 父节点值*10 + 当前节点值
AC代码
#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int MAXN = 2e6 + 10;
const int MAXC = 10;
int nxt[MAXN][MAXC], fal[MAXN], len[MAXN], idx, last; //子节点 最长回文后缀 回文长度 编号 最后处理位置
char s[MAXN];
ll ans, val[MAXN];
ll mpow(ll a, ll n, ll m)
{
ll t = 1;
while (n)
{
if (n & 1)
t = (t * a) % m;
a = (a * a) % m, n >>= 1;
}
return t;
}
inline int GetID(char c) //字符映射
{
return c - '0';
}
void Build() //初始化根节点信息
{
len[0] = 0, len[1] = -1;
idx = 1, last = 0;
fal[0] = 1;
}
int GetFail(char *s, int x, int n) //寻找最长的回文后缀
{
while (s[n - len[x] - 1] != s[n])
x = fal[x];
return x;
}
void Insert(char *s, int n) //按照顺序插入一个字符串
{
for (int i = 0; i < n; i++)
{
int c = GetID(s[i]);
int p = GetFail(s, last, i);
if (!nxt[p][c])
{
++idx;
len[idx] = len[p] + 2;
fal[idx] = nxt[GetFail(s, fal[p], i)][c];
nxt[p][c] = idx;
if (p == 1) //父节点奇根
val[idx] = c;
else
val[idx] = (c * mpow(10, len[idx] - 1, MOD) + val[p] * 10 + c) % MOD;
ans = (ans + val[idx]) % MOD; //每个新节点计算答案
}
last = nxt[p][c];
}
}