Step1 Problem:
I'll give you a string s and find the addition of palindrome strings with different natures, mod 1e9+7.
For example, s = 1111, ans = 1111 + 111 + 11 + 1
Data range:
1 <= len <= 2e6. 1 <= s[i] <= 9.
Step2 Ideas:
Pre skills: 4348 = ((4 * 10 + 3) * 10 + 4) * 10 + 8, so we can pick mod at will.
bfs starts from 0, 1. Even odd numbers are calculated separately
0 even numbers:
If the current palindrome string is empty, the result is ans = 0, and next time it becomes 11 = 1*10 + ans*10 + 1
The current palindrome string is 11, and the result is ans = 11, which becomes 1111 = 1*1000 + ans*10 + 1 next time
1 odd numbers:
The current palindrome string is empty, and the result is ans = 0. Next time, it becomes 5 = 5. / preprocessing is enough
The current palindrome string is 5, and the result is ans = 5, which becomes 555 = 1*100 + ans*10 + 5 next time
The current palindrome string is 555, and the result is ans = 555+5 = 560. Next time it becomes 55555 = 1*10000 + ans*10 + 5
Step3 Code:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 2e6+5;
const int MOD = 1e9+7;
struct node
{
int len, cnt, pos;
int next[10], fail;//only26Lowercase letters
}a[N];
int top, last;
char s[N];
void Init_Tr()
{
top = 1, last = 0;
a[0].len = 0, a[1].len = -1;
a[0].fail = 1;
}
int i;//Reducing parameter transfer can optimize a lot of time complexity
int get_id(int now)
{
while(s[i] != s[i-a[now].len-1]) now = a[now].fail;
return now;
}
void Insert()
{
int len = strlen(s+1);
for(i = 1; i <= len; i++) {
int t = s[i]-'0';
int id = get_id(last);
if(!a[id].next[t]) {
a[++top].len = a[id].len + 2;
a[top].pos = i;
a[top].fail = a[get_id(a[id].fail)].next[t];
a[id].next[t] = top;
}
last = a[id].next[t];
a[last].cnt++;
}
}
struct Q
{
int pos;
ll now, z;
};
ll solve()
{
ll ans = 0;
queue<Q> q;
for(int i = 0; i < 10; i++) {//The odd preprocessing length is 1 Palindrome string
if(a[1].next[i]) {
q.push((Q){a[1].next[i], i, 100});
}
}
while(!q.empty()) {
Q u = q.front(); q.pop();
ans += u.now;
ans %= MOD;
for(int i = 0; i < 10; i++) {
if(a[u.pos].next[i]) {
ll now = i*u.z + u.now*10 + i;
now %= MOD;
ll z = u.z*100; z %= MOD;
q.push((Q){a[u.pos].next[i], now, z});
}
}
}
q.push((Q){0, 0, 10});
while(!q.empty()) {
Q u = q.front(); q.pop();
ans += u.now;
ans %= MOD;
for(int i = 0; i < 10; i++) {
if(a[u.pos].next[i]) {
ll now = i*u.z + u.now*10 + i;
now %= MOD;
ll z = u.z*100; z %= MOD;
q.push((Q){a[u.pos].next[i], now, z});
}
}
}
return ans;
}
int main()
{
scanf("%s", s+1);
//1111111111111
Init_Tr();
Insert();
printf("%lld\n", solve());
return 0;
}