• ACM-ICPC 2018 南京赛区网络预赛 I(回文树)


    传送门

    题面:

    A number is skr, if and only if it's unchanged after being reversed. For example, "12321", "11" and "1" are skr numbers, but "123", "221" are not. FYW has a string of numbers, each substring can present a number, he wants to know the sum of distinct skr number in the string. FYW are not good at math, so he asks you for help.

    Input

    The only line contains the string of numbers SS.

    It is guaranteed that 1 le S[i] le 91≤S[i]≤9, the length of SS is less than 20000002000000.

    Output

    Print the answer modulo 10000000071000000007.

    样例输入1复制

    111111

    样例输出1复制

    123456

    样例输入2复制

    1121

    样例输出2复制

    135

    题目来源

    ACM-ICPC 2018 南京赛区网络预赛

    题意:

        给你一串由数字组成的字符串,让你找到这个字符串中本质不同的回文串,并将他们转化为数字并求和,答案对1e9+7取模。

    题目分析:

        因为涉及本质回文子串的问题,因此我们可以考虑用回文树去解决。

        这道题中,我们只需要在在插入字符的过程中模拟高精加的过程即可。

        具体的做法是:我们先找到当前结点now的最长回文后缀的长度(即),此时对于结点now,他所能构成的最长回文后缀的长度即为

        故加上字符后的值即为(因为回文,所以头尾字符相同)。

        最后我们还需加上之前的值

        即当前的值为:

        最后我们只需要遍历回文树上的所有结点上的值即可。

    代码:

    #include <bits/stdc++.h>
    #define maxn 2000005
    using namespace std;
    typedef long long ll;
    ll sum[maxn],base[maxn];
    const int mod=1e9+7;
    char str[maxn];
    struct PAM{//回文树
        int next[maxn][10],len[maxn],fail[maxn],S[maxn];
        int id,n,last;
        int newnode(int x){
            for(int i=0;i<10;i++){
                next[id][i]=0;
            }
            len[id]=x;
            return id++;
        }
        void init(){
            id=0;
            newnode(0),newnode(-1);
            n=last=0;
            fail[0]=1;
            S[n]=-1;
        }
        int getfail(int x){
            while(S[n-len[x]-1]!=S[n]) x=fail[x];
            return x;
        }
        void Insert(int c){
            S[++n]=c;
            int cur=getfail(last);
            if(!next[cur][c]){
                int now=newnode(len[cur]+2);
                fail[now]=next[getfail(fail[cur])][c];
                next[cur][c]=now;
                sum[now]=(base[len[cur]+1]*c+c+sum[cur]*10)%mod;//统计当前结点所形成的回文串的数值
            }
            last=next[cur][c];
        }
    }pam;
    int main()
    {
        scanf("%s",str);
        pam.init();
        int len=strlen(str);
        base[0]=1;
        for(int i=1;i<len;i++) base[i]=base[i-1]*10%mod;//先预处理出来所有的10的幂
        base[0]=0;
        for(int i=0;i<len;i++){
            pam.Insert(str[i]-'0');
        }
        ll res=0;
        for(int i=2;i<pam.id;i++){//统计答案
            res=(res+sum[i])%mod;
        }
        printf("%lld
    ",res);
    }
    
  • 相关阅读:
    如何遍历对象,hasOwnProperty()方法,和 in 的区别【CordeWars实践】 Pete, the baker
    去除字符串内所有空格【在CodeWars中实践】The Hashtag Generator
    JS 去掉小数点
    "写出下列代码的执行结果"一直不会做?【JS Event Loop】
    【CodeWars】Large Factorials (计算阶乘)
    去掉数组或者字符串中相邻的重复数据
    纯CSS绘制三角形(各种角度)
    3.坐标系与轴心点
    2.blender的基本操作与动画案例挑战
    CF1470E Strange Permutation
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11007195.html
Copyright © 2020-2023  润新知