题目链接:点击这里
解题思路:
首先我们知道一个长度为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;
}