• 计蒜客-2018南京网络赛skr(回文树)


    题意:给你一个数字字符串,问你本质不同的回文子串的和是多少

    解题思路:用回文树直接可以把本质不同的回文子串都跑出来,然后分别遍历以奇树为节点和以偶数为节点的两颗回文树就行了

    代码:

    #include<bits/stdc++.h>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    typedef long long LL;
    const int maxn = 2000000 + 10;
    const int N = 10 ;
    const int mod=1e9+7;
    ll sum[maxn];
    struct Palindromic_Tree {
        int next[maxn][N] ;//next指针,next指针和字典树类似,指向的串为当前串两端加上同一个字符构成
        int fail[maxn] ;//fail指针,失配后跳转到fail指针指向的节点
        int cnt[maxn] ;
        int num[maxn] ;
        int len[maxn] ;//len[i]表示节点i表示的回文串的长度
        int S[maxn] ;//存放添加的字符
        int last ;//指向上一个字符所在的节点,方便下一次add
        int n ;//字符数组指针
        int tot ;//节点指针
    
        LL val[maxn];
    
        int newnode ( int l ) {//新建节点
            for ( int i = 0 ; i < 10 ; ++ i ) next[tot][i] = 0 ;
            cnt[tot] = 0 ;
            num[tot] = 0 ;
            val[tot] = 0LL;
            len[tot] = l ;
            return tot ++ ;
        }
    
        void init () {//初始化
            tot = 0 ;
            newnode (  0 ) ;
            newnode ( -1 ) ;
            last = 0 ;
            n = 0 ;
            S[n] = -1 ;//开头放一个字符集中没有的字符,减少特判
            fail[0] = 1 ;
        }
    
        int get_fail ( int x ) //get_fail函数就是让找到第一个使得S[n - len[last] - 1] == S[n]的last
        {//和KMP一样,失配后找一个尽量最长的
            while ( S[n - len[x] - 1] != S[n] ) x = fail[x] ;//如果没有构成回文,那么去找最长的后缀回文子串
            return x ;//如果能构成回文,说明可以通过之前的点+一个字符构成新的回文
        }
    
        void add ( int c ) {
            c -= '0' ;
            S[++ n] = c ;
            int cur = get_fail ( last ) ;//通过上一个回文串找这个回文串的匹配位置
            if ( !next[cur][c] ) {//如果这个回文串没有出现过,说明出现了一个新的本质不同的回文串
                int now = newnode ( len[cur] + 2 ) ;//新建节点
                fail[now] = next[get_fail ( fail[cur] )][c] ;//和AC自动机一样建立fail指针,以便失配后跳转
                next[cur][c] = now ;
                num[now] = num[fail[now]] + 1 ;
            }
            int pre = cur;
            last = next[cur][c];
            cnt[last] ++ ;
        }
    
        void count () {
            for ( int i = tot - 1 ; i >= 0 ; -- i ) cnt[fail[i]] += cnt[i] ;
            //父亲累加儿子的cnt,因为如果fail[v]=u,则u一定是v的子回文串!
        }
    }run;
    char s[maxn];
    ll ans1,ans2;
    void dfs(int x,ll pre,ll len)
    {
            for(ll i=0;i<10;i++)
            {
                if(run.next[x][i])
                {
                    ll tmp=((sum[len-1]*i)%mod+pre*10+i)%mod;tmp%=mod;
                    ans1+=tmp;ans1%=mod;
                    dfs(run.next[x][i],tmp,len+2);
                }
            }
    }
    void dfs2(int x,ll pre,ll len)
    {
        ll tmp;
        for(ll i=0;i<10;i++)
        {
            if(run.next[x][i])
            {
                if(len==1)
                {
                    ans2=ans2+i;tmp=i;
                }
                else
                {
                    tmp=((sum[len]*i)%mod+pre*10+i)%mod;tmp%=mod;
                    ans2+=tmp;ans2%=mod;
                }
                 dfs(run.next[x][i],tmp,len+2);
            }
        }
    }
    int main()
    {
        sum[0]=1;
        for(int i=1;i<=maxn;i++)
        {
            sum[i]=sum[i-1]*10;sum[i]%=mod;
        }
        scanf("%s",&s);
        run.init();
        int nn=strlen(s)-1;
        for(int i=0;i<=nn;i++)
        run.add(s[i]);
        dfs(0,0,2);
        dfs2(1,0,1);
        ll ans=ans1+ans2;
        cout<<ans<<endl;
    }
  • 相关阅读:
    电路中的VCC和VDD
    动态数码管 什么是位选 段选
    pytest文档62-内置fixture之request
    pytest文档61-fixture之name参数使用别名
    pytest文档60-pytest.main()的使用
    python笔记49-yaml文件中变量的使用(锚点& 与 引用*)
    python笔记48-面试题:m1={'a':1,'b':2,'c':1} 将同样的value的key集合在list里,输出{1:['a','c'],2:['b']}
    jenkins学习15-Allure报告不用登陆也能给领导看
    python接口自动化35-pyppeteer-install下载没反应,r.html.render() 下载无反应问题解决
    kvm内存优化--KSM
  • 原文地址:https://www.cnblogs.com/huangdao/p/10808430.html
Copyright © 2020-2023  润新知