The Number of Palindromes

Problem Description
Now, you are given a string S. We want to know how many distinct substring of S which is palindrome.
Input
The first line of the input contains a single integer T(T<=20), which indicates number of test cases.
Each test case consists of a string S, whose length is less than 100000 and only contains lowercase letters.
Output
For every test case, you should output "Case #k:" first in a single line, where k indicates the case number and starts at 1. Then output the number of distinct substring of S which is palindrome.
Sample Input
3
aaaa
abab
abcd
Sample Output
Case #1: 4
Case #2: 4
Case #3: 4
 
 
【题意】
  统计一个字符串内有多少个不同的回文串。
 
 
【分析】
  这道题主要是去重。
  一开始我打的去重还是很有问题,还是看别人的才打出来了。
  
  把原串反向加入到原串后面,中间插入特殊字符。后缀数组求sa、height。
  分奇偶,奇串和偶串肯定是不同种的。然后对于一个位置i,找到对应位置,用rmq求区间min。
  去重:用cnt记录目前计算的回文长度与height的min值(所以这里计算的时候要按字符串大小顺序计算)。
  如果有新增回文串,就加进去,并更新cnt
 
  主要是最后一步,要好好理解。
 
代码如下:
 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define Maxl 200010
#define INF 0xfffffff int c[Maxl];
int n,cl,l; int mymin(int x,int y) {return x<y?x:y;}
int mymax(int x,int y) {return x>y?x:y;} char s[Maxl];
void init()
{
scanf("%s",s);
l=strlen(s);cl=;
for(int i=;i<l;i++) c[++cl]=s[i]-'a'+;
c[++cl]=;
for(int i=l-;i>=;i--) c[++cl]=s[i]-'a'+;
} int sa[Maxl],rk[Maxl],Rs[Maxl],y[Maxl],wr[Maxl];
void get_sa(int m)
{
memcpy(rk,c,sizeof(rk));
for(int i=;i<=m;i++) Rs[i]=;
for(int i=;i<=cl;i++) Rs[rk[i]]++;
for(int i=;i<=m;i++) Rs[i]+=Rs[i-];
for(int i=cl;i>=;i--) sa[Rs[rk[i]]--]=i; int ln=,p=;//p表示目前有多少个不一样的rk
while(p<cl)
{
int k=;
for(int i=cl-ln+;i<=cl;i++) y[++k]=i;
for(int i=;i<=cl;i++) if(sa[i]>ln) y[++k]=sa[i]-ln;
for(int i=;i<=cl;i++)
wr[i]=rk[y[i]]; for(int i=;i<=m;i++) Rs[i]=;
for(int i=;i<=cl;i++) Rs[wr[i]]++;
for(int i=;i<=m;i++) Rs[i]+=Rs[i-];
for(int i=cl;i>=;i--) sa[Rs[wr[i]]--]=y[i]; for(int i=;i<=cl;i++) wr[i]=rk[i];
for(int i=cl+;i<=cl+ln;i++) wr[i]=;
p=,rk[sa[]]=;
for(int i=;i<=cl;i++)
{
if(wr[sa[i]]!=wr[sa[i-]]||wr[sa[i]+ln]!=wr[sa[i-]+ln]) p++;
rk[sa[i]]=p;
}
ln*=;m=p;
}
sa[]=rk[]=;
} int height[Maxl];
void get_he()
{
int k=;
for(int i=;i<=cl;i++) if(rk[i]!=)
{
int j=sa[rk[i]-];
if(k) k--;
while(c[i+k]==c[j+k]&&i+k<=cl&&j+k<=cl) k++;
height[rk[i]]=k;
}
height[]=;
} int d[Maxl][];
void rmq_init()
{
for(int i=;i<=cl;i++) d[i][]=height[i];
for(int j=;(<<j)<=cl;j++)
for(int i=;i+(<<j)-<=cl;i++)
d[i][j]=mymin(d[i][j-],d[i+(<<j-)][j-]);
} int rmq(int x,int y)
{
int t;
if(x>y) t=x,x=y,y=t;
x++;
int k=;
while((<<(k+))<=y-x+) k++;
return mymin(d[x][k],d[y-(<<k)+][k]);
} int ans;
void ffind()
{
int cnt=;ans=;
//奇
for(int i=;i<=cl-n;i++)
{
cnt=mymin(cnt,height[i]);
if(sa[i]<=l)
{
int j=rk[cl-sa[i]+];
int tem=rmq(i,j);
if(tem>cnt)
{
ans+=(tem-cnt);
cnt=tem;
}
}
}
//偶
cnt=;
for(int i=;i<=cl-n;i++)
{
cnt=mymin(cnt,height[i]);
if(sa[i]<=l)
{
int j=rk[cl-sa[i]+];
int tem=rmq(i,j);
if(tem>cnt)
{
ans+=tem-cnt;
cnt=tem;
}
}
}
} int main()
{
int T,kase=;
scanf("%d",&T);
while(T--)
{
init();
get_sa(+n);
get_he();
rmq_init();
ffind();
printf("Case #%d: %d\n",++kase,ans);
}
return ;
}

[HDU3948]

2016-07-19 09:46:16

 

【HDU3948】 The Number of Palindromes (后缀数组+RMQ)的更多相关文章

  1. spoj687 REPEATS - Repeats (后缀数组+rmq)

    A string s is called an (k,l)-repeat if s is obtained by concatenating k>=1 times some seed strin ...

  2. 【uva10829-求形如UVU的串的个数】后缀数组+rmq or 直接for水过

    题意:UVU形式的串的个数,V的长度规定,U要一样,位置不同即为不同字串 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&am ...

  3. POJ 3693 后缀数组+RMQ

    思路: 论文题 后缀数组&RMQ 有一些题解写得很繁 //By SiriusRen #include <cmath> #include <cstdio> #includ ...

  4. HDU 6194 string string string(后缀数组+RMQ)

    string string string Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  5. Codeforces Round #422 (Div. 2) E. Liar 后缀数组+RMQ+DP

    E. Liar     The first semester ended. You know, after the end of the first semester the holidays beg ...

  6. HDU2459 后缀数组+RMQ

    题目大意: 在原串中找到一个拥有连续相同子串最多的那个子串 比如dababababc中的abababab有4个连续的ab,是最多的 如果有同样多的输出字典序最小的那个 这里用后缀数组解决问题: 枚举连 ...

  7. hdu 2459 (后缀数组+RMQ)

    题意:让你求一个串中连续重复次数最多的串(不重叠),如果重复的次数一样多的话就输出字典序小的那一串. 分析:有一道比这个简单一些的题spoj 687, 假设一个长度为l的子串重复出现两次,那么它必然会 ...

  8. ural 1297(后缀数组+RMQ)

    题意:就是让你求一个字符串中的最长回文,如果有多个长度相等的最长回文,那就输出第一个最长回文. 思路:这是后缀数组的一种常见的应用,首先把原始字符串倒转过来,然后接在原始字符串的后面,中间用一个不可能 ...

  9. 【BZOJ 3473】 字符串 (后缀数组+RMQ+二分 | 广义SAM)

    3473: 字符串 Description 给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串? Input 第一行两个整数n,k. 接下来n行每行一个字符串 ...

随机推荐

  1. 基于heartbeat的单播方式实现tomcat高可用

    1.节点规划 在master.backup节点上添加eth0.eth1两网卡,具体添加过程,参考“基于VMware为CentOS 6.5配置两个网卡” 2.IP规划   master backup e ...

  2. QT开发pjsip的VOIP,A8平台运行

    QT开发pjsip的VOIP 开发环境 平台:A8 环境:Linux-3.0.8 实现功能:使用QT开发VOIP进行初始化.拨号.挂起 测试工具:minisipserver服务器 效果 界面: min ...

  3. XC应用系列作品(Android应用)

    XC系列应用,如真题园手机客户端1.1等应用已经分别在 360手机助手.腾讯应用宝.百度手机助手.小米应用商店.豌豆荚.应用汇.木蚂蚁等安卓市场平台上线了! 本页面的系列应用是本人的开发的一Andro ...

  4. django开发框架之jumpserver

    发现一个不错的开源堡垒机 jumpserver: https://github.com/ibuler/jumpserver 最开始看的是jumpserver2.0.0 版本,具体的实现方式是: 1. ...

  5. js--小结⑥---typeof

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. 对java框架的几点认识

    java框架实在是太多了,网上一抄一大段,根本就了解不到什么.我还是以我的经验来说一下j2ee的框架.1.首先力推struts2框架,这是最经典的框架(可以说没有“之一”).可以帮你快速搭建出一个MV ...

  7. struts 2读书笔记-----struts2的开发流程

    一.将struts 2的lib文件夹下地commons-fileupload.jar.commons-io.jar.freemarker.jar.javassist.jar.ognl.jar.stru ...

  8. XML的基本操作

    所有 XML 文档中的文本均会被解析器解析.只有 CDATA 区段(CDATA section)中的文本会被解析器忽略.CDATA 部分中的所有内容都会被解析器忽略.CDATA 部分由 "& ...

  9. [XML] resources的Xml配置文件 (转载)

    <?xml version="1.0" encoding="utf-8" ?> <resources> <language> ...

  10. 写一个最简单的 Server

    import java.net.*;import java.io.*;public class Server{ public static void main(String[] args) throw ...