[palindrome Tree & & sum of different palindrome strings in essence] ACM-ICPC 2018 Nanjing area network preliminaries I. Skr

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;
}

Posted by seriousdamage on Thu, 02 Jan 2020 15:26:36 -0800