ACM-ICPC 2018 南京赛区网络预赛 I题 - 回文自动机

题目链接:点击这里

 

解题思路:

首先我们知道一个长度为n的字符串的所有不同的子串不会超过2*n种,所以不同的回文子串自然不会超过n种。

对于回文自动机,与AC自动机相同的是也有一个fail指针指向第一个相近的且被其包含的一个回文串.

所以建树方法基本与ac自动机相同,不懂自动机的可以去查。

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mx = 2e6 + 20;
const int N = 12 ;
const int mod = 1e9 + 7;

ll qpow(ll x,ll y)
{
	ll ans = 1;
	while(y){
		if(y&1) ans = ans*x%mod;
		y >>= 1;
		x = x*x%mod;
	}
	return ans;
}
 
ll ans,v[mx];

struct Word {
    int ch[mx][N] ;
    int fail[mx] ;
    int len[mx],S[mx] ;
    int last ;
    int n ;
    int sz ;
    int newnode ( int l ) {
       	memset(ch[sz],0,sizeof(ch[sz]));
        len[sz] = l ;
        return sz ++ ;
    }
    void init () {
        memset(fail,0,sizeof(fail));
        sz = 0 ;
        newnode (  0 ) ;
        newnode ( -1 ) ;
        last = 0 ;
        n = 0 ;
        S[n] = -1 ;
        fail[0] = 1 ;
    }
 
    int getfail ( int x ) {
        while ( S[n -len[x]-1] != S[n] ) x = fail[x] ;
        return x ;
    }
 
    void add ( int c ) {
        c -= '0' ;
        S[++ n] = c ;
        int cur = getfail (last) ;
        if (!ch[cur][c]) {
            int now = newnode (len[cur] + 2) ;
            fail[now] = ch[getfail(fail[cur])][c] ;
            ch[cur][c] = now ;
            
            last = ch[cur][c];
            if(len[cur]==-1) v[last] = c;
    		else v[last] = (1ll*v[cur]*10+1ll*c*qpow(10,len[cur]+1)+c)%mod;
    		ans = (ans+v[last])%mod;
        }
        last = ch[cur][c] ;
    }
 
}word;
char str[mx];
int main(){
    scanf("%s",str);
    word.init();
    int len = strlen(str);
    for(int i=0;i<len;i++){
        word.add(str[i]);
    }
    printf("%lld\n",ans);
    return 0;
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值