题目描述
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...srsatisfy 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.
输入
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.
输出
For each test case, output one line containing |S| integers. Any two adjacent integers are separated by a space.
样例输入
复制样例数据
abababa
样例输出
7 0 0 0 3 0 0
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll mod=1e9+7;
const int modp=998244353;
const int maxn=300050;
const double eps=1e-6;
#define lowbit(x) x&(-x)
#define lson root << 1
#define rson root << 1 | 1
#define INF 0x3f3f3f3f
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
int dcmp(double x){
if(fabs(x)<eps)return 0;
return (x>0)?1:-1;
}
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
ll qmod(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1)
{
ans=(ans*a)%mod;
}
b>>=1;
a=(a*a)%mod;
}
return ans;
}
ll ret[maxn];
ull has[maxn],pp[maxn];
const ull hash1 = 201326611;
ull gethas(int l,int r){//字符串哈希,用来判是否一样
if(l==0)return has[r];
return has[r]-has[l-1]*pp[r-l+1];
}
bool check(int l,int r){//二分check前后两部分
int len=r-l+1;
int mid=(l+r)>>1;
if(len&1)return gethas(l,mid)==gethas(mid,r);
else return gethas(l,mid)==gethas(mid+1,r);
}
struct Palindromic_Tree {//回文树
int nxt[maxn][30], fail[maxn], cnt[maxn];
int num[maxn], len[maxn], s[maxn], id[maxn];
int last, n, p;
int newnode(int l) {
memset(nxt[p], 0, sizeof(nxt[p]));
cnt[p] = num[p] = 0;
len[p] = l;
return p++;
}
void init() {
p = 0;
newnode(0), newnode(-1);
last = n = 0;
s[0] = -1;
fail[0] = 1;
}
int get_fail(int x) {
while (s[n - len[x] - 1] != s[n]) x = fail[x];
return x;
}
void add(int c) {
c -= 'a';
s[++n] = c;
int cur = get_fail(last);
if (!nxt[cur][c]) {
int now = newnode(len[cur] + 2);
fail[now] = nxt[get_fail(fail[cur])][c];
nxt[cur][c] = now;
num[now] = num[fail[now]] + 1;
}
last = nxt[cur][c];
cnt[last]++, id[last] = n;
}
ll Count() {
for (int i = p - 1; i >= 0; i--) cnt[fail[i]] += cnt[i];
for (int i = 2; i < p; i++) {
if (check(id[i] - len[i], id[i] - 1)) {
ret[len[i]] += cnt[i];
}
}
return 0;
}
} pam;
char str[maxn];
int main()
{
pp[0]=1;
for(int i=1;i<=maxn;i++){
pp[i]=hash1*pp[i-1];
}
while(~scanf("%s",str)){
memset(ret,0,sizeof(ret));
pam.init();
int len=strlen(str);
has[0]=str[0];
for(int i=0;i<len;i++){
pam.add(str[i]);
}
for(int i=1;i<len;i++){
has[i]=has[i-1]*hash1+str[i];
}
pam.Count();
for(int i=1;i<len;i++){
printf("%lld ",ret[i]);
}
printf("%lld\n",ret[len]);
}
return 0;
}
https://blog.youkuaiyun.com/Clove_unique/article/details/53750322