Sample Input

aca
aaaa

Sample Output

3
15

题意: 多组输入,每次给定字符串S(|S|<1e5),求多少对不相交的回文串。

思路:可以用回文树求出以每个位置结尾的回文串数,那么累加得到前缀和; 倒着再做一遍得到每个位置为开头的回文串数,乘正向求出的前缀和即可。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep2(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int maxn=;
struct PAT
{
struct node{
int len,num,fail,son[];
}t[maxn];
int last,n,tot,s[maxn];
void init()
{
memset(t,,sizeof(t));
tot=last=; n=;
t[].len=; t[].len=-;
t[].fail=t[].fail=;
s[]=-;
}
int add(int c){
int p=last; s[++n]=c;
while(s[n]!=s[n--t[p].len]) p=t[p].fail;
if(!t[p].son[c]){
int v=++tot,k=t[p].fail;
while(s[n]!=s[n-t[k].len-]) k=t[k].fail;
t[v].fail=t[k].son[c];
t[v].len=t[p].len+;
t[v].num=t[t[v].fail].num+;
t[p].son[c]=v;
}
last=t[p].son[c];
return t[last].num;
}
}T;
ll ans,sum[maxn];char c[maxn];
int main()
{
while(~scanf("%s",c+)){
int N=strlen(c+);
T.init(); ans=;
rep(i,,N) sum[i]=sum[i-]+T.add(c[i]-'a');
T.init();
rep2(i,N,) ans+=sum[i-]*T.add(c[i]-'a');
printf("%lld\n",ans);
}
return ;
}

最新文章

  1. ios UI 适配布局相关文章
  2. 洛谷P1736 创意吃鱼法
  3. protected 和default的区别
  4. .NET Web开发总结(二)
  5. javascript之面向对象程序设计(对象和继承)
  6. Python环境搭建中解决C编译的问题
  7. Android源代码分析之Framework的MediaPlayer
  8. android平板Home键的监听
  9. Windows Phone开发(35):使用Express Blend绘图
  10. Swoole笔记(四)
  11. 【Hadoop】NameNode
  12. Javascript数组求和的方法总结 以及由斐波那契数列得到的启发
  13. 仿qq最新侧滑菜单
  14. High Availability手册(2): 架构
  15. Guess Number Game
  16. ROSETTA使用技巧随笔--relax使用
  17. 汇编 shr 逻辑右移指令,shl 逻辑左移指令,SAL 算术左移指令,SAR 算术右移指令
  18. Struts2 文件下载(中文处理方法以及控制下载文件名称和扩展名)
  19. POJ 2752 KMP中next数组的理解
  20. Android 压力测试工具Monkey

热门文章

  1. ajax请求成功前,加载中loading显示
  2. span 超出部分换行
  3. Oracle 如何循环查询结果集,进行新增或修改
  4. MySql多个count查询
  5. 基于bootstrap的后台左侧导航菜单和点击二级菜单刷新二级页面时候菜单展开显示当前菜单
  6. ASCII编码、Unicode编码、UTF-8
  7. 【框架】PageObject(一)
  8. sys 模块
  9. Standalone的更改方式
  10. .net core webapi 配置swagger调试界面