题意:
给你一个字符串S,让你求出S中所有本质不同的回文串,然后把这些回文串转换成数字后相加的和
例如:
1121 共有4个本质不同的回文串: 1 + 11 + 121 + 2 = 135
题解:
预处理出每个前缀形成的数字的值,然后根据回文自动机的性质,很显然在i点有一个长度为len的回文串,那么这个区间对应的数即为:起点为i的前缀表示数字-起点为i-len的前缀表示的数字,就表示这个区间表示的数了,然后累加即可
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 2e6+50;
const int MOD = 1000000007;
LL ans[MAXN],qmi[MAXN],res;
int nxt[MAXN][10],fail[MAXN],len[MAXN],tot,last,n;
char s[MAXN];
inline void Init(){
len[0]=0,len[1]=-1;
fail[0]=fail[1]=1;
tot=last=1;
qmi[0]=1;
for(int i=1;i<=n;i++) qmi[i]=qmi[i-1]*10%MOD,ans[i]=(ans[i-1]*10+s[i]-'0')%MOD;
}
inline void Insert(char ch,int en){
int rt=last;
while(s[en]!=s[en-len[rt]-1]) rt=fail[rt];
if(!nxt[rt][ch-'0']){
len[++tot]=len[rt]+2;
res = ((res+ans[en]-ans[en-len[tot]]*qmi[len[tot]])%MOD+MOD)%MOD;
int tmp=fail[rt];
while(s[en]!=s[en-len[tmp]-1]) tmp=fail[tmp];
fail[tot]=nxt[tmp][ch-'0'];
nxt[rt][ch-'0']=tot;
}
last=nxt[rt][ch-'0'];
}
int main(){
scanf("%s",s+1);
n=strlen(s+1); Init();
for(int i=1;i<=n;i++) Insert(s[i],i);
printf("%lld\n",res);
return 0;
}