zoukankan      html  css  js  c++  java
  • 计蒜客-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;
    }
  • 相关阅读:
    Python 学习日记 第七天
    Python 学习日记 第六天
    Python 学习日记 第五天
    Python 学习日记 第四天
    Redis 中的数据类型及基本操作
    Asp.net mvc 中View 的呈现(二)
    Asp.net mvc 中View的呈现(一)
    Asp.net mvc 中Action 方法的执行(三)
    Asp.net mvc 中Action 方法的执行(二)
    Asp.net mvc 中Action 方法的执行(一)
  • 原文地址:https://www.cnblogs.com/huangdao/p/10808430.html
Copyright © 2011-2022 走看看