回文树(统计所有回文串的个数) - MCCME 1750 Подпалиндромы

本文介绍了一种在给定字符串中高效统计所有回文串数量的方法,包括算法原理、实现细节以及时间复杂度分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Подпалиндромы 

Problem's Link:  http://informatics.mccme.ru//mod/statements/view.php?chapterid=1750#


 

Mean: 

给你一个长度不超过1e5的字符串,要统计总共有多少个回文串。(第一次刷俄语题,还好有google翻译)。

analyse:

如果题目说是不同回文串的话,这题就是一个裸的回文树。

由于要求所有子串的回文数,所以我们在插入的时候还需要使用suffixLink往上走统计答案。

Time complexity: O(N)

 

Source code: 

/*
* this code is made by crazyacking
* Verdict: Accepted
* Submission Date: 2015-08-17-19.13
* Time: 0MS
* Memory: 137KB
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#define  LL long long
#define  ULL unsigned long long
using namespace std;

const int MAXN = 105000;
struct node
{
      int next [ 26 ];
      int len;
      int sufflink;
      int num;
};
int len;
char s [ MAXN ];
node tree [ MAXN ];
int num; // node 1 - root with len -1, node 2 - root with len 0
int suff; // max suffix palindrome
long long ans;
bool addLetter( int pos)
{
      int cur = suff , curlen = 0;
      int let = s [ pos ] - 'a';
      while( true)
      {
            curlen = tree [ cur ]. len;
            if( pos - 1 - curlen >= 0 &&s [ pos - 1 - curlen ] ==s [ pos ]) break;
            cur = tree [ cur ]. sufflink;
      }
      if( tree [ cur ]. next [ let ])
      {
            suff = tree [ cur ]. next [ let ];
            return false;
      } suff = ++ num;
      tree [ num ]. len = tree [ cur ]. len + 2;
      tree [ cur ]. next [ let ] = num;
      if( tree [ num ]. len == 1)
      {
            tree [ num ]. sufflink = 2;
            tree [ num ]. num = 1;
            return true;
      }
      while( true)
      {
            cur = tree [ cur ]. sufflink;
            curlen = tree [ cur ]. len;
            if( pos - 1 - curlen >= 0 && s [ pos - 1 - curlen ] == s [ pos ])
            {
                  tree [ num ]. sufflink = tree [ cur ]. next [ let ];
                  break;
            }
      }
      tree [ num ]. num = 1 + tree [ tree [ num ]. sufflink ]. num;
      return true;
}
void initTree()
{
      num = 2; suff = 2;
      tree [ 1 ]. len = - 1; tree [ 1 ]. sufflink = 1;
      tree [ 2 ]. len = 0; tree [ 2 ]. sufflink = 1;
}
int main()
{
      gets(s);
      initTree();
      for( int i = 0;s [ i ]; i ++)
      {
            addLetter( i);
            ans += tree [ suff ]. num;
      } cout << ans << endl;
      return 0;
}

 

转载于:https://www.cnblogs.com/crazyacking/p/4737477.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值