zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Android中查找一个Layout中指定的子控件
    常用代码
    数据库连接池配置
    分享一个电子书网站
    怎么快速入手一个项目在没有人指导的情况下
    压测如何观测jvm,就是使用jmx来实现jvm监控
    工具类
    APP开发和web开发的区别
    网站切流量
    互联网主题分析
  • 原文地址:https://www.cnblogs.com/Rhein-E/p/10213370.html
Copyright © 2011-2022 走看看