回文自动机( I Love Palindrome String)
题目描述
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.
∙ 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×10 5 ) containing only lowercase English letters.
It is guaranteed that the sum of |S| in all test cases is no larger than 4×10 6 .
Each case starts with a line containing a string S(1≤|S|≤3×10 5 ) containing only lowercase English letters.
It is guaranteed that the sum of |S| in all test cases is no larger than 4×10 6 .
输出
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
回文自动机:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int MAX = 3e5+100;
const int ALP = 26;
struct Palindromic_Tree {
int son[MAX][ALP];
int fail[MAX];
int cnt[MAX];
int num[MAX];
int len[MAX];
vector<int> to[MAX];
int S[MAX];
int last;
int n;
int p;
int newnode(int l) {
memset(son[p], 0, sizeof(son[p]));
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;
to[1].push_back (0);
}
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 (!son[cur][c]) {
int now = newnode(len[cur] + 2);
fail[now] = son[get_fail(fail[cur])][c];
to[son[get_fail(fail[cur])][c]].push_back (now);
son[cur][c] = now;
num[now] = num[fail[now]] + 1;
}
last = son[cur][c];
cnt[last]++;
}
void count() {
for (int i = p - 1; i >= 0; i--) cnt[fail[i]] += cnt[i];
}
} xxx;
const int maxn = 3e5+100;
int ans[maxn];
bool vis[maxn];
void dfs(int u) {
if(vis[(xxx.len[u]+1)/2]) {
ans[xxx.len[u]]+=xxx.cnt[u];
}
if(xxx.len[u]>=0) vis[xxx.len[u]]=1;
for( auto v:xxx.to[u]) {
dfs (v);
}
if(xxx.len[u]>=0) vis[xxx.len[u]]=0;
return;
}
int main()
{
string s;
while (cin>>s) {
int siz = s.length ();
for(int i=0;i<=siz;i++) {
xxx.to[i].clear ();
ans[i]=0;
}
xxx.init ();
for(auto x : s) xxx.add (x);
xxx.count ();
dfs (1);
ans[1]=siz;
for(int i=1;i<=siz;i++) {
printf ("%d",ans[i]);
if(i!=siz) printf (" ");
else printf ("\n");
}
}
}
回文自动机+dfs;
1
|
DFS
|
回溯维护不同长度回文串个数。