HDU3948:后缀数组+马拉车(本质不同回文子串统计)
来源:互联网 发布:php部署到apache 编辑:程序博客网 时间:2024/06/11 09:35
题意:给出一个字符串,求其 本质不同的 回文子串的个数。
如果有小伙伴WA了无数次,请尝试模拟一下aabaa这个串,答案应该是5。(本菜鸡就WA了一晚上)
题解:回文子串可以考虑先来个O(n)的马拉车预处理,这样每个回文子串长度必然是计数,那么我们可以统计本质不同的(正中间的字符+右半边串)回文子串个数。然后可以考虑用后缀自动机统计答案。这道题的关键的关键在于去重的处理。去重要求去掉:h[i]范围内已经被统计过的串。那么可以用一个变量维护 目前已经被统计过的长度。要注意到h数组和马拉车的lc数组是没什么关系的。
Code:
#include<bits/stdc++.h>using namespace std;#define rank rkconst int MAX = 2e5+10000;char ch[MAX];int cntA[MAX],cntB[MAX],A[MAX],B[MAX],tsa[MAX],rank[MAX],SA[MAX],lc[MAX],h[MAX];int n,t;int Cas =1; void init(){ memset(ch,0,sizeof ch); ch[0]='z'+1;}void input(){ scanf("%s",ch+1); n = strlen(ch+1); ch[n*2+1]='#'; for (int i=n;i>=1;i--){ ch[i*2] = ch[i]; ch[i*2-1] ='#'; } n = n*2+1; ch[n+1]='\0';}void get_SA(){ for (int i=0;i<=10000;i++) cntA[i]=0; for (int i=1;i<=n;i++) cntA[ch[i]]++; for (int i=1;i<=10000;i++) cntA[i]+=cntA[i-1]; for (int i=n;i>=1;i--) SA[cntA[ch[i]]--] =i; rank[SA[1]]=1; for (int i=2;i<=n;i++){ rank[SA[i]]=rank[SA[i-1]]; if (ch[SA[i]]!=ch[SA[i-1]]) rank[SA[i]]++; } for (int step = 1;rank[SA[n]]<n;step<<=1){ for (int i=0;i<=n;i++)cntA[i]=cntB[i]=0; for (int i=1;i<=n;i++){ cntA[A[i]=rank[i]]++; cntB[B[i]=(i+step<=n)?rank[i+step]:0]++; } for (int i=1;i<=n;i++) cntA[i]+=cntA[i-1],cntB[i]+=cntB[i-1]; for (int i=n;i>=1;i--) tsa[cntB[B[i]]--] =i; for (int i=n;i>=1;i--) SA[cntA[A[tsa[i]]]--] = tsa[i]; rank[SA[1]]=1; for (int i=2;i<=n;i++){ rank[SA[i]]=rank[SA[i-1]]; if (A[SA[i]]!=A[SA[i-1]]||B[SA[i]]!=B[SA[i-1]]) rank[SA[i]]++; } }}void get_Height(){ for (int i=1,j=0;i<=n;i++){ if (j) j--; while (ch[i+j]==ch[SA[rank[i]-1]+j])j++; h[rank[i]]=j; }}void Manacher(){ lc[1]=1; int k=1; for (int i=2;i<=n;i++){// printf("%d %d\n",i,k); int p = k+lc[k]-1; if (i<=p){ lc[i]=min(lc[2*k-i],p-i+1); }else{ lc[i]=1; } while (ch[i+lc[i]]==ch[i-lc[i]])lc[i]++; if (i+lc[i]>k+lc[k])k=i; }}void print(){ printf("%s\n",ch+1); for (int i=1;i<=n;i++){ printf("%s %d\n",ch+SA[i],lc[SA[i]]); }}void solve(){ get_SA(); get_Height(); Manacher(); print(); long long res =0;// cout<<"1: "<<res<<endl;int cnt=0; for (int i=2;i<=n;i++){ cnt = min(cnt,h[i]); res+=max(0,lc[SA[i]]-min(h[i],cnt)); // cout<<i<<" "<<res<<endl; if (lc[SA[i]]>cnt){ cnt = lc[SA[i]]; } }// cout<<res/2<<endl; printf("Case #%d: %I64d\n",Cas++,res/2);}int main(){ scanf("%d",&t); while (t--){ init(); input(); solve(); } return 0;}
阅读全文
0 0
- HDU3948:后缀数组+马拉车(本质不同回文子串统计)
- hdu3948——后缀数组统计不同回文子串的个数
- 后缀数组(不同的回文字串)hdu3948
- 最长回文子串(马拉车)
- hihoCoder-1032 - 最长回文子串(Manacher 马拉车)
- 求最大回文子串(马拉车算法)
- 最长回文子串-----“马拉车”算法
- hdu 3948 后缀数组统计不同回文串的个数
- hihoCoder 最长回文子串(manacher算法:马拉车)
- Manacher马拉车算法求最长回文子串
- mannachar(马拉车)求最长回文子串
- New Distinct Substrings (后缀数组,统计有多少个不同的子串)
- Manacher算法--O(n)回文子串算法(马拉车算法)
- 【LeetCode】Longest Palindromic Substring(最长回文子串1)[马拉车Manacher算法]
- ural 1297(求最长回文子串,后缀数组)
- Palindrome后缀数组判断回文子串
- HDU 4622 本质不同的子串个数:后缀自动机
- spoj694 Distinct Substrings(后缀数组+统计不同子串的个数)
- windows 下搭建web服务器
- springmvc spring hibernate maven fastjson 配置
- windows 下搭建邮件服务器
- 基于springMVC的HelloWorld实例
- 再谈微积分下放中学的现实意义
- HDU3948:后缀数组+马拉车(本质不同回文子串统计)
- AI challenger 场景分类(1) 生成tfrecord文件
- 数据库创建索引的优缺点
- 提高SQL查询效率的30种方法
- java的成员访问控制
- 详细讲解二叉树三种遍历方式的递归与非递归实现
- 小度所理解的信息化与实际工作中的应用之我见
- 麦枫定制OEM服装行业ERP管理系统,无用户数与时间限制
- mybatis.xml报错:The element type "mapper" must be terminated by the matching end-tag "