【noi.ac#1764】 T1

题目

题目描述
读入一个字符串 SS, 只包含阿拉伯数字.

问 SS 有多少个回文子串 S[i,j]S[i,j], 使得 S[i,j]S[i,j] 构成一个不含前导零并且能被 33 整除的非负整数.

输入格式
输入只有一行, 包括一个字符串 SS, 仅包含阿拉伯数字.

输出格式
输出只有一个整数, 表示答案.

样例 1
输入

01001001000
输出

9
说明
在样例中, 含有 88 个 00, 以及一个 10010011001001.

思路

如果 X X X 是个回文串, 记 p ( X ) = 1 p(X) = 1 p(X)=1, 否则 p ( X ) = 0 p(X) = 0 p(X)=0.

f ( i ) f(i) f(i) 为右端点为 i i i 的回文子串的个数. 即 f ( i ) = ∑ j = 1 i p ( S [ j , i ] ) f(i) = \sum_{j = 1}^i p(S[j, i]) f(i)=j=1ip(S[j,i]).

F ( i ) F(i) F(i) f ( i ) f(i) f(i) 的前缀和, 即 F ( i ) = ∑ j = 1 i f ( i ) F(i) = \sum_{j=1}^i f(i) F(i)=j=1if(i).

那么如果一个回文子串是 S [ x , y ] S[x, y] S[x,y], 我们可以统计出在其左侧与其相交的回文串的个数为 F ( y ) − F ( x − 1 ) F(y) - F(x - 1) F(y)F(x1).

我们从被减数和减数两个方向去观察.

F ( x ) F(x) F(x) 作为被减数的次数, 其实就是 f ( x ) f(x) f(x).

F ( x ) F(x) F(x) 作为减数的次数, 其实是 ∑ i = x + 1 ∣ S ∣ p ( S [ x , i ] ) \sum_{i=x + 1}^{|S|} p(S[x, i]) i=x+1Sp(S[x,i]), 这其实是 S [ x , ∣ S ∣ ] S[x, |S|] S[x,S] 的回文前缀的个数, 把串倒过来求一边后缀树即可.

代码

#include
#define int long long
using namespace std;
int read(){
	int f=1,ans=0;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
	return ans*f;
}
const int maxn=4000001;
char str[maxn];int N,A[maxn],S[maxn],yjy;
struct PAM{
	int siz[maxn],len[maxn],S[maxn],fa[maxn],ch[maxn][27],tot,las,R[maxn];
	bool f[maxn];
	void Init(){tot=1,las=0;len[1]=-1,fa[0]=1;return;}
	void ins(int c,int N){
		int u=las;while(str[N-len[u]-1]!=str[N]) u=fa[u];
		if(!ch[u][c]){
			int nw=++tot,v=fa[u];
			while(str[N-len[v]-1]!=str[N]) v=fa[v];
			fa[nw]=ch[v][c],ch[u][c]=nw,len[nw]=len[u]+2;
		}las=ch[u][c];siz[las]++;R[las]=N;
	}
}T;
int Query(int l,int r){return S[r]-S[l-1];}
signed main(){
	scanf("%s",str+1);N=strlen(str+1);
	T.Init();
	for(int i=1;i<=N;i++) T.ins(str[i]-'0',i),A[i]=str[i]-'0',S[i]=S[i-1]+A[i]; 
	for(int i=T.tot;i>=2;i--) T.siz[T.fa[i]]+=T.siz[i];
	for(int i=2;i<=T.tot;i++) if(A[T.R[i]]!=0&&(Query(T.R[i]-T.len[i]+1,T.R[i])%3)==0){
		yjy+=T.siz[i];
	}
	for(int i=1;i<=N;i++) yjy+=(A[i]==0);
	printf("%lld\n",yjy);return 0;
}

你可能感兴趣的:(【noi.ac#1764】 T1)