HDU - 5658 CA Loves Palindromic(回文自动机/哈希+树状数组)
题目链接:点击查看
题目大意:给出一个字符串 s ,接下来给出 m 个查询,每次查询的形式会给出一个 l 和 r ,问区间 [ l , r ] 内有多少个本质不同的回文子串
题目分析:因为查询的次数比较多,所以我们可以预处理出答案然后O(1)回答,因为回文自动机的时间复杂度为O(n)级别的,我们可以枚举 n * n 个子串依次记录答案
2020.11.11更新:
然后发现哈希也能乱搞,原理就是将每个字符串用哈希映射成不同的数字,然后就转换成 “区间内不同数字的个数” 了,用树状数组或线段树离线随便做就好了
如果用 map 记录哈希的话,时间复杂度就是 O( n * n * logn + q * logn )
悄咪咪的说一句,打算在校赛上放这个题,因为哈希乱搞也是可以搞过去的嘛。。
代码:
回文自动机
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<sstream>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e3+100;char s[N];int n,ans[N][N];struct Palindrome_tree
{int nxt[N][26];int fail[N]; // 当前节点最长回文后缀的节点int len[N]; // 当前节点表示的回文串的长度int cnt[N]; // 当前节点回文串的个数, 在getcnt后可得到全部int sed[N]; // 以当前节点为后缀的回文串的个数(并不是表示第i结尾的回文串的种类数,如果要求每个点结尾的数的回文串个数,得用last)int record[N]; //record记录了节点回文串的结束位置char s[N];int tot; // 节点个数int last; // 上一个节点int n;//当前字符串的长度 void init(){tot = n = 0;memset(fail, 0, sizeof fail);memset(cnt, 0, sizeof cnt);memset(sed, 0, sizeof sed);memset(len, 0, sizeof len);memset(nxt, 0, sizeof nxt);}void build(){len[0] = 0, len[1] = -1; // 0为偶数长度根, 1为奇数长度根tot = 1, last = 0;fail[0] = 1;}int getfail(int x, int n){while (s[n - len[x] - 1] != s[n]||n-len[x]-1<0) // 比较x节点回文串新建两端是否相等//n-len[x]-1<0这个是我自己加的,多组的时候光第一个条件是不够的,所以有错请手动删除x = fail[x]; // 若不同, 再比较x后缀回文串两端return x;}void insert(char ch){int c = ch - 'a';//全小写要用a 全大写要用A 不然会错s[++n]=ch;int p = getfail(last, n);// 得到第i个字符可以加到哪个节点的两端形成回文串if (!nxt[p][c]){tot++;len[tot] = len[p] + 2; // 在p节点两端添加两个字符fail[tot] = nxt[getfail(fail[p], n)][c]; //tot点的后缀回文,可以由上一个节点的后缀回文尝试得到sed[tot] = sed[fail[tot]] + 1; // 以当前节点为结尾的回文串个数nxt[p][c] = tot; // 新建节点}last = nxt[p][c]; // 当前节点成为上一个节点cnt[last]++; //当前节点回文串++record[last] = n;}void get_cnt(){for (int i = tot; i > 0; i--)cnt[fail[i]] += cnt[i];//fail[i] 的节点 为 i 节点的后缀回文串, 所以个数相加}
}tree;void init()
{for(int i=0;i<n;i++){tree.init();tree.build();for(int j=i;j<n;j++){tree.insert(s[j]);ans[i][j]=tree.tot-1;}}
}int main()
{
// freopen("input.txt","r",stdin);
// ios::sync_with_stdio(false);int w;cin>>w;while(w--){scanf("%s",s);n=strlen(s);init();int m;scanf("%d",&m);while(m--){int l,r;scanf("%d%d",&l,&r);printf("%d\n",ans[l-1][r-1]);}}return 0;
}
哈希+树状数组:
//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","inline","-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e5+100;char s[N];int ans[N],c[N],n,m;vector<pair<int,int>>q[N];map<ull,int>mp;ull Hash1[N],Hash2[N],p[N];void HASH()
{Hash1[0]=0,p[0]=1;for(int i=1;i<=n;i++){Hash1[i]=Hash1[i-1]*131+(s[i]-'a'+1);p[i]=p[i-1]*131;}Hash2[n+1]=0;for(int i=n;i>=1;i--)Hash2[i]=Hash2[i+1]*131+(s[i]-'a'+1);
}ull get_hash1(int l,int r)
{return Hash1[r]-Hash1[l-1]*p[r-l+1];
}ull get_hash2(int l,int r)
{return Hash2[l]-Hash2[r+1]*p[r-l+1];
}int lowbit(int x)
{return x&(-x);
}void add(int x,int val)
{for(int i=x;i<=n;i+=lowbit(i))c[i]+=val;
}int ask(int x)
{int ans=0;for(int i=x;i>0;i-=lowbit(i))ans+=c[i];return ans;
}void init(int n)
{for(int i=1;i<=n;i++)q[i].clear();HASH();memset(c,0,sizeof(int)*(n+5));mp.clear();
}int main()
{
#ifndef ONLINE_JUDGE
// freopen("data.in.txt","r",stdin);
// freopen("data.out.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);int w;cin>>w;while(w--){scanf("%s",s+1);n=strlen(s+1);init(n);scanf("%d",&m);for(int i=1;i<=m;i++){int l,r;scanf("%d%d",&l,&r);q[r].push_back({l,i});}for(int r=1;r<=n;r++){for(int l=1;l<=r;l++){if(get_hash1(l,r)==get_hash2(l,r)){if(mp[get_hash1(l,r)])add(mp[get_hash1(l,r)],-1);add(l,1);mp[get_hash1(l,r)]=l;}}for(auto it:q[r])ans[it.second]=ask(n)-ask(it.first-1);}for(int i=1;i<=m;i++)printf("%d\n",ans[i]);}return 0;
}
HDU - 5658 CA Loves Palindromic(回文自动机/哈希+树状数组)相关推荐
- 【BZOJ2434】[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组
[BZOJ2434][NOI2011]阿狸的打字机 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P ...
- 【bzoj2434】[Noi2011]阿狸的打字机 AC自动机+Dfs序+树状数组
题目描述 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小 ...
- CF-547E(Mike and Friends)后缀数组+线段树 AC自动机+DFS序+树状数组
题目链接 题意 NNN个串,每次询问区间[L,R][L,R][L,R]中有多少子串SiS_iSi 思路 把NNN个串合成一个长字符串,对这个长字符串求后缀数组,包含SiS_iSi的子串的heigh ...
- HDU多校1 - 6756 Finding a MEX(分块+二分+树状数组)
题目链接:点击查看 题目大意:给出一个 n 个点和 m 条边的无向图,每个点都有一个权值,现在需要执行 q 次操作,每次操作分为两种类型: 1 pos val :将第 pos 个点的权值修改为 val ...
- 【HDU - 6447】YJJ's Salesman(降维dp,树状数组优化dp)
题干: YJJ is a salesman who has traveled through western country. YJJ is always on journey. Either is ...
- 【HDU 5542】The Battle of Chibi (dp,树状数组优化)
目录 题目 Description Input Output Sample Input Sample Output Hint Source 思路 朴素dp 优化 代码 题目 Description C ...
- HDU - 5157 Harry and magic string(回文自动机)
题目链接:点击查看 题目大意:给出一个字符串 s ,问字符串 s 中有多少对回文子串(x,y),意思就是子串 x 和子串 y 都是回文串,且不相交(不重叠) 题目分析:可以正着跑一遍回文自动机,用一个 ...
- HDU - 5394 Trie in Tina Town(回文自动机+字典树)
题目链接:点击查看 题目大意:给出一个字典树,现在需要求出字典树上所有的回文串做出的贡献,为 出现次数*回文串长度,求出这个答案 题目链接:可以直接在字典树上dfs然后维护贡献,不过这就涉及到了回文自 ...
- 【回文自动机】bzoj3676 [Apio2014]回文串
回文自动机讲解!http://blog.csdn.net/u013368721/article/details/42100363 pam上每个点代表本质不同的回文子串.len(i)代表长度,cnt(i ...
最新文章
- python3中数字类型有哪些_python全栈_009_Python3基本数据类型--列表(示例代码)
- 登录用户Eclipse中SVN访问用户的变更办法
- 无差异曲线matlab算法,引入Matlab提高经济类线性代数应用能力
- RedHat 设置IP、网关、DNS
- iOS 在CollectionView上做展开收起动画
- hibernate两张表关联查询
- python flask 路由_Python之Flask 路由与模板语法
- 2017智能周报 | 12.10-12.17 | 工信部发布AI行动计划、各地AI研究院纷纷成立、DM证明AI存在反人类风险……
- C#Form窗体模仿PhotoShop软件,高仿真原PS界面,实现PS对图片基本操作、拍照等,计算机图形学相关
- 电脑便签、备忘录 可以直接从电脑桌面看到提醒事项的软件推荐
- 超详细的数据分析职业规划
- clappr:可扩展网页媒体播放器使用(在vue中的使用)
- 运维工程师是桥的护栏_运维工程师职务说明书
- 聚类kmeans和DBSCAN算法的简单实现
- App常用图标素材网站
- SWF代码分析与破解之路 (YueTai VIP视频信息获取工具) Socket续篇
- cmd-命令行中打开新cmd窗口
- KindEditor在线文本编辑器
- oracle怎么赋予表空间,oracle数据库创建表空间和用户并赋予权限步骤教程-Oracle...
- 【中医学】7 预防·治则·治法