标签:for extend int ems 额外 pac set mat amp
构造一种fail向同一个节点的回文机:
abadabacaba
这样caba和daba都会指向ba。
using namespace std;
typedef long long ll;
struct Node {
int len, ch[26], fail;
ll cnt;
Node(int len = 0) : len(len), fail(0) {
memset(ch, 0, sizeof(ch));
//下面是维护额外信息
cnt = 0;
}
//string str;
void show() {
printf(" len=%d\n",len);
//printf(" str=%s", str.c_str());
printf(" cnt=%lld\n", cnt);
}
};
const int MAXN = 600000;
//PalindromicAutomaton
struct PAM {
Node nd[MAXN + 5];
int len, top, last; // len为字符串长度mtop为节点个数,last为最后插入字符所对应的节点
char s[MAXN + 5];
//string ls;
int getfail(int x) { //沿着fail指针找到第一个回文后缀
while(s[len - nd[x].len - 1] != s[len])
x = nd[x].fail;
return x;
}
void init() {
len = 0, top = 0, last = 0;
nd[top] = Node(0);
nd[top].fail = 1;
nd[++top] = Node(-1);
nd[top].fail = 0;
s[0] = '$';
}
void extend(char c) {
s[++len] = c;
int now = getfail(last); //找到插入的位置
//ls = nd[now].str + c;
if(!nd[now].ch[c - 'a']) { //若没有这个节点,则新建并求出它的fail指针
nd[++top] = Node(nd[now].len + 2);
nd[top].fail = nd[getfail(nd[now].fail)].ch[c - 'a'];
nd[now].ch[c - 'a'] = top;
}
last = nd[now].ch[c - 'a'];
//nd[last].str = ls;
//下面是维护额外信息
++nd[last].cnt;
//printf("!%d\n",nd[last].cnt);
if(len %100000==0)
printf("len=%d\n", len);
}
void show() {
for(int i = top; i >= 0; --i) {
printf("node: id=%d\n", i);
nd[i].show();
printf("fail: id=%d\n", nd[i].fail);
nd[nd[i].fail].show();
puts("");
}
}
} pam;
char s[MAXN + 5];
ll ans[MAXN + 5];
int main() {
freopen("Yinku.in", "r", stdin);
while(~scanf("%s", s)) {
int n = strlen(s);
pam.init();
cout<<"!";
for(int i = 0; s[i] != '\0'; ++i)
pam.extend(s[i]);
//pam.show();
for(int i = pam.top; i >= 2; --i) {
Node *now = &pam.nd[i];
Node *fail = &pam.nd[now->fail];
fail->cnt += now->cnt;
}
//pam.show();
memset(ans, 0, sizeof(ans[0]) * (n + 1));
for(int i = pam.top; i >= 2; --i) {
printf("%d\n",i);
Node *now = &pam.nd[i];
Node *fail = &pam.nd[now->fail];
if(now->len == 1) {
ans[now->len] += now->cnt;
} else {
while((fail->len) > (now->len + 1) / 2)
fail = &pam.nd[fail->fail];
if(fail->len == (now->len + 1) / 2)
ans[now->len] += now->cnt;
}
}
for(int i = 1; i <= min(40, n); ++i)
printf("%lld%c", ans[i], " \n"[i == n]);
printf("\n");
}
return 0;
}
标签:for extend int ems 额外 pac set mat amp
原文地址:https://www.cnblogs.com/Yinku/p/11243179.html