A number is skr, if and only if it's unchanged after being reversed. For example, "12321", "11" and "1" are skr numbers, but "123", "221" are not. FYW has a string of numbers, each substring can present a number, he wants to know the sum of distinct skr number in the string. FYW are not good at math, so he asks you for help.
Input
The only line contains the string of numbers SS.
It is guaranteed that 1 \le S[i] \le 91≤S[i]≤9, the length of SS is less than 20000002000000.
Output
Print the answer modulo 10000000071000000007.
样例输入1复制
111111
样例输出1复制
123456
样例输入2复制
1121
样例输出2复制
135
题目来源
题意:
给了一个数字的字符串,问这个字符串中连续的子串是回文串的值的和。
思路:
构建一棵回文树,每次添加的时候如果判断发现是新出现的字符串则答案需要加上这个值,在计算这个值的时候,可以由它的上一个状态节点转移过来,特判一下上一个状态是奇根的就行了。
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e6+5;
const int mod=1e9+7;
typedef long long ll;
char str[maxn];
ll ans;
ll quickmod(int a,int b)
{
ll ans=1;
ll base=a;
while(b)
{
if(b&1)
ans=(ans*base)%mod;
base=(base*base)%mod;
b>>=1;
}
return ans;
}
struct Palindromic_Tree
{
int next[maxn][26] ;//next指针,next指针和字典树类似,指向的串为当前串两端加上同一个字符构成
int fail[maxn] ;//fail指针,失配后跳转到fail指针指向的节点
int cnt[maxn] ; //表示节点i表示的本质不同的串的个数(建树时求出的不是完全的,最后count()函数跑一遍以后才是正确的)
ll num[maxn] ; //表示存放的回文串的值
int len[maxn] ;//len[i]表示节点i表示的回文串的长度(一个节点表示一个回文串)
int S[maxn] ;//存放添加的字符
int last ;//指向新添加一个字母后所形成的最长回文串表示的节点。
int n ;//表示添加的字符个数。
int p ;//表示添加的节点个数。
int newnode ( int l ) //新建节点
{
for ( int i = 0 ; i < 26 ; i++ )
next[p][i] = 0 ;
cnt[p] = 0 ;
num[p] = 0 ;
len[p] = l ;
return p ++ ;
}
void init () //初始化
{
p = 0 ;
newnode ( 0 ) ;
newnode ( -1 ) ;
last = 0 ;
n = 0 ;
S[n] = -1 ;//开头放一个字符集中没有的字符,减少特判
fail[0] = 1 ;
}
int get_fail ( int x ) //和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 ;
if(len[cur]==-1)
{
ans=(ans+c)%mod;
num[now]=c;
}
else
{
num[now]=((num[cur]*10)%mod+c)%mod+((c*quickmod(10,len[now]-1))%mod)%mod;
ans=(ans+num[now])%mod;
}
}
last = next[cur][c] ;
cnt[last] ++ ;
}
void count ()
{
for ( int i = p - 1 ; i >= 0 ; -- i )
cnt[fail[i]] += cnt[i] ;
//父亲累加儿子的cnt,因为如果fail[v]=u,则u一定是v的子回文串!
}
} tree;
int main()
{
scanf("%s",str);
int len=strlen(str);
tree.init();
for(int i=0;i<len;i++)
{
tree.add(str[i]);
}
printf("%lld\n",ans);
return 0;
}