题意:求一个串中有多少不同的回文串。

分析:这一题的关键是如何去重,我表示我现在还没理解为什么这样去重,先放这里过两天再看!!

//不同回文子串数目
#include <iostream>
#include <string>
#include <cmath>
#include <map>
using namespace std;
#define N 200010
int ws1[N],wv[N],wa[N],wb[N];
int rank1[N],height[N],sa[N];
char str[N];
int a[N],n;
int dp[N][25],vis[N];int mmin(int a,int b)
{return a>b?b:a;
}int cmp(int *r,int a,int b,int l)
{return r[a]==r[b] && r[a+l]==r[b+l];
}void da(int *r,int *sa,int n,int m)
{int i,j,p,*x=wa,*y=wb,*t;for(i=0;i<m;i++)ws1[i]=0;for(i=0;i<n;i++)ws1[x[i]=r[i]]++;for(i=1;i<m;i++)ws1[i]+=ws1[i-1];for(i=n-1;i>=0;i--)sa[--ws1[x[i]]]=i;for(j=1,p=1;p<n;j*=2,m=p){for(p=0,i=n-j;i<n;i++)y[p++]=i;for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;for(i=0;i<n;i++)wv[i]=x[y[i]];for(i=0;i<m;i++)ws1[i]=0;for(i=0;i<n;i++)ws1[wv[i]]++;for(i=1;i<m;i++)ws1[i]+=ws1[i-1];for(i=n-1;i>=0;i--)sa[--ws1[wv[i]]]=y[i];for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;}
}void calheight(int *r,int *sa,int n)
{int i,j,k=0;for(i=1;i<=n;i++)rank1[sa[i]]=i;for(i=0;i<n;height[rank1[i++]]=k)for(k?k--:0,j=sa[rank1[i]-1];r[i+k]==r[j+k];k++) ;
}void RMQ(int n)//RMQ预处理
{int i,j;memset(dp,127,sizeof(dp));for(i=1;i<=n;i++)dp[i][0]=height[i];for(j=1;(1<<j)<=n;j++)for(i=1;i+(1<<j)-1<=n;i++)dp[i][j]=mmin(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}int lcp(int l,int r)//求最长公共前缀
{int a=rank1[l],b=rank1[r];if(a>b)swap(a,b);a++;int t=(int)(log(double(b-a+1))/log(2.00));return mmin(dp[a][t],dp[b-(1<<t)+1][t]);
}int main()
{int T,i,k,ca=0,s,t,ans;scanf("%d",&T);while(T--){scanf("%s",str);k=strlen(str);str[k]='9';for(i=0;i<k;i++)str[i+k+1]=str[k-i-1];str[2*k+1]='0';n=2*k+2;str[n]='\0';for(i=0;i<n;i++)  a[i]=(int)str[i]; da(a,sa,n,'z'+1);calheight(a,sa,n-1);RMQ(n-1);ans=0;memset(vis,0,sizeof(vis));s=0;for(i=2;i<n;i++)//奇数的时候
        {s=mmin(s,height[i]);if(vis[2*k-sa[i]]){t=lcp(sa[i],2*k-sa[i]);if(t>s){ans+=t-s;s=t;}}elsevis[sa[i]]=1;}memset(vis,0,sizeof(vis));s=0;for(i=2;i<n;i++)//偶数的时候
        {s=mmin(s,height[i]);if(!sa[i])continue;if(vis[2*k-sa[i]+1]){t=lcp(sa[i],2*k-sa[i]+1);if(t>s){ans+=t-s;s=t;}}elsevis[sa[i]]=1;}printf("Case #%d: %d\n",++ca,ans);}return 0;
}

转载于:https://www.cnblogs.com/jiangjing/p/3250981.html

hdu 3948(后缀数组+RMQ)相关推荐

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

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

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

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

  3. hdu 5008 Boring String Problem(后缀数组+rmq)

    题目链接:hdu 5008 Boring String Problem 题意: 给你一个字符串,有q个询问,每次询问该字符串所有的子串中字典序第k小的是哪个串,输出位置,如果有多个位置,输出最靠左的那 ...

  4. HDU - 4552 怪盗基德的挑战书(后缀数组+RMQ/KMP+dp)

    题目链接:点击查看 题目大意:给出一个字符串,统计每个前缀在字符串中出现的次数之和 题目分析:可以直接先用后缀数组跑出来height,再用RMQ跑出来任意两个后缀的height,我们可以将题意转换为求 ...

  5. HDU - 6194 string string string(后缀数组+RMQ+容斥)

    题目链接:点击查看 题目大意:给出一个字符串和一个数字 k,问字符串中出现次数恰好等于 k 次的字串有多少个 题目分析:在跑完后缀数组后,我们可以用sa数组求解,具体做法是枚举起点,找长度为 k 的s ...

  6. HDU 6194 string string string 后缀数组 + RMQ(线段树)

    传送门:HDU6194 题意:问给定字符串中有多少种出现k次的子串. 思路:首先想到后缀数组经典问题,求出现不少于k次的子串的最大长度,类似的这题肯定就是在height数组上搞事情啦. 将height ...

  7. URAL - 1297 Palindrome(后缀数组+RMQ)

    题目链接:点击查看 题目大意:给出一个字符串,求出最长的回文子串 题目分析:如果用以往的方法求,不可避免的都需要枚举所有子串,时间复杂度就已经到达了O(n),而后缀数组可以通过O(n)预处理后得到所有 ...

  8. hdu 6194 后缀数组

    题意:一个字符串,查询恰好出现k次的子串的数目 思路:后缀数组在height上进行操作.我们直接枚举长度为k的区间求min值,但是要注意的是直接这么算是会重复的,同时也可能超过k次,这样我们就需要把枚 ...

  9. POJ - 3693 Maximum repetition substring(后缀数组+RMQ)

    题目链接:点击查看 题目大意:给出一个字符串,求出字符串中 重复次数最多的连续重复子串 ,如果有多个答案,输出字典序最小的 题目分析:又是一个模板题,这里放一个大佬的博客,讲的很清楚: https:/ ...

最新文章

  1. 《Java编程思想》笔记13.字符串
  2. 自动化录制脚本java_自动化java+webdriver常用的一些脚本
  3. Containers vs Serverless:怎么选择?
  4. php请求路由,PHP 新手入门指南 - 表单请求与路由
  5. Ubuntu9.10安装常用软件
  6. 数据中心真能促进乡村经济吗?
  7. 使用Boost_MPI进行并行编程
  8. 关于aop:pointcut的expression配制说明及JoinPoint
  9. C#| 使用String.Format()方法将小数点前的数字四舍五入
  10. where 泛型类型约束 default 关键字
  11. android 登录qq接口开发,三方登录-QQ登录开发-Android(as版本)
  12. 网络连接正常,IE不能打开网页的全面解决方法
  13. javascript定时器的计时事件
  14. A64的原装风扇真让人头痛
  15. 手机浏览器调用摄像头扫码
  16. 【Vue】报错信息: [WDS] Errors while compiling. Reload prevented.
  17. 双系统 Win10下安装Linux(单/双硬盘)
  18. 一些公开免费的后台数据接口
  19. IOS性能检测工具-Instruments
  20. Big-Small (根号分治) 学习笔记

热门文章

  1. 如何在 Windows Server 2003 中创建漫游用户配置文件
  2. Unity AOP 处理异常的方法
  3. 如何区分SCSI卡和RAID卡?
  4. software engineering interview domain
  5. Cambridge center for digital innovation at judge business school
  6. 【转】光栅化操作阶段
  7. IPHONE 64位和32位
  8. ubuntu下远程控制LinuxWindow桌面
  9. Helm V3 新版本发布
  10. python3高阶函数:map(),reduce(),filter()的区别