BZOJ4480[JSOI2013]快乐的jyy

*回文自动机第一题*

回文自动机学习地址:https://www.cnblogs.com/nianheng/p/9814530.html

指针版模板地址:https://blog.csdn.net/zp1ng/article/details/80425494

很明显的回文自动机,优秀做法是把两个串插入一个自动机,分别统计数量,统计答案时相同节点上两个数量相乘加入答案。

当然你也可以像我一样不优秀地开两个自动机然后统计答案的时候再开个pair队列,跑得很慢qwq。

网上的题解都是数组版的回文自动机,我来贡献一发指针版吧,代码丑陋不堪 捂脸(/ω\)。

跑得很慢的丑陋的代码↓

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iomanip>
  4 #include <iostream>
  5 #include <queue>
  6 
  7 typedef long long LL;
  8 struct PalindromeAutomata {
  9     struct Node {
 10         Node *fail, *next[26];
 11         int len, cnt;
 12     } * root0, *root1, *last;
 13     int length;
 14     char string[50010];
 15 
 16     PalindromeAutomata();
 17     Node *newNode(int = 0);
 18     void init();
 19     void release();
 20     void insert(int);
 21     void insert(char *);
 22     void pushUp();
 23 } PAM1, PAM2;
 24 char s1[50010], s2[50010];
 25 
 26 LL bfs();
 27 
 28 int main() {
 29 //    freopen("4480.in", "r", stdin);
 30 //    freopen("4480.out", "w", stdout);
 31     std::ios::sync_with_stdio(false);
 32     std::cin >> s1 >> s2;
 33     PAM1.init();
 34     PAM2.init();
 35     PAM1.insert(s1);
 36     PAM2.insert(s2);
 37     PAM1.pushUp();
 38     PAM2.pushUp();
 39     std::cout << bfs() << std::endl;
 40 
 41     return 0;
 42 }
 43 PalindromeAutomata::Node *PalindromeAutomata::newNode(int l) {
 44     Node *res = new Node();
 45     res->len = l;
 46     res->cnt = 0;
 47     res->fail = root0;
 48     for (int i = 0; i < 26; i++) res->next[i] = root0;
 49     return res;
 50 }
 51 PalindromeAutomata::PalindromeAutomata() { memset(this, 0, sizeof(PalindromeAutomata)); }
 52 void PalindromeAutomata::init() {
 53     if (root0) release();
 54     root0 = newNode();
 55     for (int i = 0; i < 26; i++) root0->next[i] = root0;
 56     root1 = newNode(-1);
 57     root0->fail = root1->fail = root1;
 58 }
 59 void PalindromeAutomata::insert(char *str) {
 60     length = 0;
 61     last = root0;
 62     int l = strlen(str);
 63     for (int i = 0; i < l; i++) insert(str[i] - 'A');
 64 }
 65 void PalindromeAutomata::insert(int c) {
 66     string[++length] = 'A' + c;
 67     Node *p = last;
 68     while (string[length - p->len - 1] != string[length]) p = p->fail;
 69     if (p->next[c] == root0) {
 70         Node *np = newNode(p->len + 2), *q = p->fail;
 71         while (string[length - q->len - 1] != string[length]) q = q->fail;
 72         np->fail = q->next[c];
 73         p->next[c] = np;
 74     }
 75     last = p->next[c];
 76     last->cnt++;
 77     //std::cerr << last->len << std::endl;
 78 }
 79 void PalindromeAutomata::release() {
 80     std::queue<Node *> q;
 81     q.push(root0);
 82     q.push(root1);
 83     while (!q.empty()) {
 84         Node *p = q.front();
 85         for (int i = 0; i < 26; i++)
 86             if (p->next[i] != root0) q.push(p->next[i]);
 87         delete p;
 88     }
 89 }
 90 void PalindromeAutomata::pushUp() {
 91     std::vector<Node *> q;
 92     q.push_back(root1);
 93     q.push_back(root0);
 94     for (int i = 0; i < q.size(); i++)
 95         for (int j = 0; j < 26; j++)
 96             if (q[i]->next[j] != root0) q.push_back(q[i]->next[j]);
 97     for (int i = q.size() - 1; i >= 0; i--) q[i]->fail->cnt += q[i]->cnt;
 98 }
 99 typedef PalindromeAutomata::Node Node;
100 LL bfs() {
101     LL res = 0;
102     std::queue<std::pair<Node *, Node *> > q;
103     q.push(std::make_pair(PAM1.root0, PAM2.root0));
104     q.push(std::make_pair(PAM1.root1, PAM2.root1));
105     while (!q.empty()) {
106         std::pair<Node *, Node *> p = q.front();
107         q.pop();
108         if (p.first != PAM1.root0 && p.first != PAM1.root1)
109             res += p.first->cnt * 1ll * p.second->cnt;
110         for (int i = 0; i < 26; i++)
111             if (p.first->next[i] != PAM1.root0 && p.second->next[i] != PAM2.root0)
112                 q.push(std::make_pair(p.first->next[i], p.second->next[i]));
113     }
114     return res;
115 }

 

posted @ 2019-01-03 11:43  Rhein_E  阅读(372)  评论(0编辑  收藏  举报