HDU 6599:I Love Palindrome String Manacher+回文自动机

题意

Problem Description
You are given a string S=s1s2…s|S| containing only lowercase English letters. For each integer i∈[1,|S|] , please output how many substrings slsl+1…sr satisfy the following conditions:

∙ r−l+1 equals to i.

∙ The substring slsl+1…sr is a palindrome string.

∙ slsl+1…s⌊(l+r)/2⌋ is a palindrome string too.

|S| denotes the length of string S.

A palindrome string is a sequence of characters which reads the same backward as forward, such as madam or racecar or abba.

Input
There are multiple test cases.

Each case starts with a line containing a string S(1≤|S|≤3×105) containing only lowercase English letters.

It is guaranteed that the sum of |S| in all test cases is no larger than 4×106.

Output
For each test case, output one line containing |S| integers. Any two adjacent integers are separated by a space.

Sample Input
abababa

Sample Output
7 0 0 0 3 0 0

分析

这个统计回文数量的题,就想到了回文树,利用fail来统计答案
对于串的前半段还需要回文,我们对于回文自动机上的一个点代表的串,记录一个位置另外用manacher判断就行
(一开始其实直接倍增跳fail,但是又是WA又是TLE,最后还是没能过)

代码

#include <bits/stdc++.h>
#define ll long long
#define N 300002
using namespace std;
char ss[N],s[N<<1];
int rad[N<<1]; int pp,mx,len,l;
struct PAM
{
  int g[N][27],len[N],fail[N],siz[N],last,tot,n,ed[N];
  PAM(){tot=0;}
  void init()
  {
    for(int i=0;i<=tot;i++) for(int j=1;j<=26;j++) g[i][j] = 0;
	for(int i=0;i<=tot;i++) len[i] = fail[i] = siz[i] = ed[i] = 0;
	n = 0; last = 0; tot = 1; fail[1] = fail[0] = 1; len[1] = -1; len[0] = 0; 
  }
  void ins(int nx)
  {
	n++; int p = last;
	while(ss[n-len[p]-1] != ss[n]) p = fail[p];
	if(!g[p][nx])
	{
	  int np = ++tot; len[np] = len[p] + 2;
	  int q = fail[p];
	  while(ss[n-len[q]-1] != ss[n]) q = fail[q];
	  fail[np] = g[q][nx]; g[p][nx] = np;
	}p=g[p][nx]; last=p; siz[p]++; ed[p] = n; 
  }	  
}p;

int cnt[N];

int main()
{
  //freopen("a.in","r",stdin);
  //freopen("a.out","w",stdout);
  while(scanf("%s",ss+1)!=EOF)
  {
    len = strlen(ss+1); l = len;
	
	p.init();
	for(int i=1;i<=l;i++)
	  p.ins(ss[i]-'a'+1);
	for(int i=p.tot;i>=1;i--) p.siz[p.fail[i]] += p.siz[i];
	
    s[0] = '#'; for(int i=1;i<=len;i++) s[(i<<1)-1] = '*' , s[i<<1] = ss[i]; s[(len<<1)+1] = '*'; s[(len<<1)+2] = '$'; len = (len<<1) + 2;
    pp=1; mx=0; for(int i=1;i<=len;i++) rad[i] = 0;
    for(int i=1;i<=len;i++)
	{
	  if(mx > i) rad[i] = min(rad[(pp<<1)-i],mx-i+1);
	  while(s[i+rad[i]] == s[i-rad[i]]) rad[i]++;
	  if(mx < i+rad[i]-1){mx = i+rad[i]-1; pp=i;}
	}
	
	for(int i=1;i<=l;i++) cnt[i] = 0;
	for(int i=p.tot;i>=1;i--)
	{
	  int l = p.ed[i] - p.len[i] + 1; int r = p.ed[i];
	  int mid = (l+r)>>1; int x =( (l<<1) + (mid<<1) ) >> 1;
	  // printf("%intd %intd %intd %intd\n",l,r,p.siz[i],x);
	  if(rad[x] - 1 >= mid-l+1) cnt[p.len[i]]+=p.siz[i];
	}
	
	for(int i=1;i<=l;i++) printf("%d%c",cnt[i]," \n"[i==l]);
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_39708759/article/details/97281848