Problem Description

最后来个字符串签个到吧,这题其实并不难,所需的算法比较基础,甚至你们最近还上过课。

为了降低难度,免得所有人爆零。这里给几个提示的关键字 :字符串,回文,二分,哈希. 注意要对奇偶回文分开二分

这样还不会做,说明基础有所欠缺。

给你一个字符串A和一个字符串B,请你求一个满足以下要求的所有字符串中,最长的字符串C的长度:

  1. C必须同时是A和B的子串,即A和B中都必须存在一个子区间和C长得一样

  2. C必须是一个回文,即正过来读和反过来读都一样

Input

多组数据,请处理到EOF

每组数据包含,两行,每行都是仅由小写字符构成的字符串,代表A和B。

对于30%的数据。

保证|A|,|B|<=1000,且单个文件的字符总数小于10000

对于100%的数据

保证|A|,|B|<=100000,且单个文件的字符总数小于2e6

其中70%的数据答案为奇数哦

因为没有处理掉字符串尾巴上多余的'\r',所以为了防止读到'\r' 推荐使用scanf("%s");

链接

思路:

更新2.0:

旺神nb。发现A了之后就能看所有人代码了

终于找到Hash的O(n)找公共子串的方法了,直接用unordered_map储存所有满足长度的回文子串。unordered_map查询接近常数级,就是O(1),插入反正比map快,所以总体就是O(n)级。

然后就从7000ms瞬间降到1400ms

代码2.0我没有预处理成全奇回文,而是直接分类奇偶二分。显然我们可以优化一下,奇偶遍历存在与否时可以直接两步两步走,因为奇偶的回文中心刚好交错。然后我们假如先二分奇数,得到一个长度R,那么我二分偶数回文半径至少R / 2 + 1,否则没有意义。我们直接用unordered_map储存s串的回文答案,然后O(n)判断p中有没有,如果怕Hash冲突,可以再验算一边是否一样。

然后我发现时限变成4000ms了...7s的代码卡掉了...只能用2.0的代码过...

这道题后缀数组也能做,JQtxdy +

----------------代码1.0分割线(已T)----------------------------

按照旺神的思路来。

我是把串先按照Manacher处理成只有奇数回文,然后找到最大回文串R,显然最终答案只可能是R,R-2,R-4....那么我直接二分这个最终长度。然后用hash找是否存在这个长度的公共子串,但是我只会Hash的O(nlogn + m)写法啊。在T了几发之后发现题目时限又开大了,8000ms用7400ms擦过,旺神nb。

代码2.0:

#include<cmath>
#include<set>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 200000 + 10;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
char s[maxn], p[maxn], snew1[maxn];
int pos[maxn], num[maxn];
ull hs[maxn], hp[maxn], fac[maxn], q[maxn];
inline ull getHashP(int l, int r){return hp[r] - (l == 0? 0 : hp[l - 1]) * fac[r - l + 1];
}
inline ull getHashS(int l, int r){return hs[r] - (l == 0? 0 : hs[l - 1]) * fac[r - l + 1];
}
int lens, lenp, lenSnew;
int init(int len){int cnt = 0;snew1[cnt] = '$';for(int i = 0; i < len; i++){snew1[++cnt] = '#';snew1[++cnt] = s[i];}snew1[++cnt] = '#';snew1[++cnt] = '\0';return cnt;
}
int Manacher(){int cnt = init(lens);lenSnew = cnt;int id = 0, ans = -1;for(int i = 2; i < cnt; i++){if(pos[id] + id > i){pos[i] = min(pos[2 * id - i], pos[id] + id - i);}else pos[i] = 1;while(snew1[i - pos[i]] == snew1[i + pos[i]])pos[i]++;if(id + pos[id] < i + pos[i])id = i;ans = max(ans,pos[i] - 1);}return ans; //长度
}
bool mid(int l, int r, ull aim){while(l <= r){int m = (l + r) >> 1;if(q[m] >= aim){if(q[m] == aim) return true;r = m - 1;}else l = m + 1;}return false;
}
unordered_map<ull, int> mp;
//$#a#a#a#0
bool checkJi(int len){mp.clear();for(int i = 2; i + len - 1 < lenSnew; i += 2){   //sif(pos[i] - 1 >= len){int R = len / 2;int position = i / 2 - 1;   //实际位置mp[getHashS(position - R, position + R)] = 1;}}for(int i = 0; i + len - 1 < lenp; i++){ull aim = getHashP(i, i + len - 1);if(mp.count(aim)) return true;}return false;
}
//$#c#a#a#a#a#0
bool checkOu(int len){mp.clear();for(int i = 1; i + len - 1 < lenSnew; i += 2){   //sif(pos[i] - 1 >= len){int R = len / 2;int position = i / 2 - 1;   //实际位置mp[getHashS(position - R + 1, position + R)] = 1;}}for(int i = 0; i + len - 1 < lenp; i++){ull aim = getHashP(i, i + len - 1);if(mp.count(aim)) return true;}return false;
}
int main(){fac[0] = 1;for(int i = 1; i < 100010; i++)fac[i] = fac[i - 1] * seed;while(scanf("%s%s", s, p) != EOF){lens = lenp = 0;hs[0] = hp[0] = 0;for(int i = 0; s[i] != '\0'; i++){  //hashif(i == 0) hs[i] = s[i];else hs[i] = hs[i - 1] * seed + s[i];lens++;}for(int i = 0; p[i] != '\0'; i++){if(i == 0) hp[i] = p[i];else hp[i] = hp[i - 1] * seed + p[i];lenp++;}int R = Manacher(); //马拉车返回s最大长度int l, r, ans = 0;l = 1, r = R / 2;while(l <= r){  //偶int m = (l + r) >> 1;if(checkOu(m * 2)){l = m + 1;ans = m * 2;}else r = m - 1;}l = ans / 2, r = R / 2;while(l <= r){  //奇int m = (l + r) >> 1;if(checkJi(m * 2 + 1)){l = m + 1;ans = max(m * 2 + 1, ans);}else r = m - 1;}printf("%d\n", ans);}return 0;
}

代码:

#include<cmath>
#include<set>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 200000 + 10;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
char s[maxn], p[maxn], snew1[maxn], snew2[maxn];
int pos[maxn], num[maxn];
ull hs[maxn], hp[maxn], fac[maxn], q[maxn];
inline ull getHashP(int l, int r){return hp[r] - (l == 0? 0 : hp[l - 1]) * fac[r - l + 1];
}
inline ull getHashS(int l, int r){return hs[r] - (l == 0? 0 : hs[l - 1]) * fac[r - l + 1];
}
int lens, lenp, lenSnew;
int init(int len){int cnt = 0;snew1[cnt] = '$';for(int i = 0; i < len; i++){snew1[++cnt] = '#';snew1[++cnt] = s[i];}snew1[++cnt] = '#';snew1[++cnt] = '\0';return cnt;
}
int Manacher(){int cnt = init(lens);lenSnew = cnt;int id = 0, ans = -1;for(int i = 2; i < cnt; i++){if(pos[id] + id > i){pos[i] = min(pos[2 * id - i], pos[id] + id - i);}else pos[i] = 1;while(snew1[i - pos[i]] == snew1[i + pos[i]])pos[i]++;if(id + pos[id] < i + pos[i])id = i;ans = max(ans,pos[i] - 1);}return ans; //长度
}
bool mid(int l, int r, ull aim){while(l <= r){int m = (l + r) >> 1;if(q[m] >= aim){if(q[m] == aim) return true;r = m - 1;}else l = m + 1;}return false;
}
bool check(int len){int tol = 0;for(int i = 0; i + len - 1 < lenp; i++){    //p子串q[tol++] = getHashP(i, i + len - 1);}sort(q, q + tol);for(int i = 2; i < lenSnew; i += 2){  //找sif(pos[i] - 1 >= len){int R = len / 2;int position = i / 2 - 1;   //实际位置ull aim = getHashS(position - R, position + R);if(mid(0, tol - 1, aim)){return true;}}}return false;
}
int main(){fac[0] = 1;for(int i = 1; i < maxn; i++)fac[i] = fac[i - 1] * seed;while(scanf("%s%s", snew1, snew2) != EOF){lens = 0, lenp = 0;//改成全奇回文s[lens++] = '0';for(int i = 0; snew1[i] != '\0'; i++){s[lens++] = snew1[i];s[lens++] = '0';}p[lenp++] = '0';for(int i = 0; snew2[i] != '\0'; i++){p[lenp++] = snew2[i];p[lenp++] = '0';}hs[0] = hp[0] = 0;for(int i = 0; i < lens; i++){  //hashif(i == 0) hs[i] = s[i];else hs[i] = hs[i - 1] * seed + s[i];}for(int i = 0; i < lenp; i++){if(i == 0) hp[i] = p[i];else hp[i] = hp[i - 1] * seed + p[i];}int cnt = lenSnew;int L = 1, R = Manacher(); //马拉车返回最大长度int l = 1, r = R / 2; //R = 2 * r + 1int ans = 0;while(l <= r){int m = (l + r) >> 1;if(check(2 * m + 1)){ans = 2 * m + 1;l = m + 1;}else{r = m - 1;}}printf("%d\n", ans / 2);}return 0;
}

转载于:https://www.cnblogs.com/KirinSB/p/10663751.html

FJUT3703 这还是一道数论题(二分 + hash + manacher 或者 STL + hash 或者 后缀数组 + hash)题解...相关推荐

  1. 后缀数组 + Hash + 二分 or Hash + 二分 + 双指针 求 LCP ---- 2017icpc 青岛 J Suffix (假题!!)

    题目链接 题目大意: 就是给你n个串每个串取一个后缀,要求把串拼起来要求字典序最小!! sum_length_of_n≤5e5sum\_length\_of\_n\leq 5e5sum_length_ ...

  2. SPOJ 220 Relevant Phrases of Annihilation(后缀数组+二分答案)

    [题目链接] http://www.spoj.pl/problems/PHRASES/ [题目大意] 求在每个字符串中出现至少两次的最长的子串 [题解] 注意到这么几个关键点:最长,至少两次,每个字符 ...

  3. 【2020.10.31 洛谷团队赛 普及组】T2 U138180 神仙数论题

    题目背景 众所周知,ax≡b(modp)a^x≡b(modp)ax≡b(modp) 和 xa≡b(modp)x^a ≡b(modp)xa≡b(modp) 都可以在较为优秀的时间复杂度内求解. Quan ...

  4. 1402 后缀数组 (hash+二分)

    描述 后缀数组 (SA) 是一种重要的数据结构,通常使用倍增或者DC3算法实现,这超出了我们的讨论范围.在本题中,我们希望使用快排.Hash与二分实现一个简单的 O(n log^2⁡n ) 的后缀数组 ...

  5. 数据范围BZOJ 3209(花神的数论题-数位统计+1,被数据范围坑了)

    PS:今天上午,非常郁闷,有很多简单基础的问题搞得我有些迷茫,哎,代码几天不写就忘.目前又不当COO,还是得用心记代码哦! 3209: 花神的数论题 Time Limit: 10 Sec Memory ...

  6. [XSY] 简单的数论题(数学、构造)

    简单的数论题 m(a3+b3)=n(c3+d3)m(a^3+b^3)=n(c^3+d^3)m(a3+b3)=n(c3+d3) 考虑因式分解(a3+b3),(c3+d3):考虑因式分解(a^3+b^3) ...

  7. [数位dp] bzoj 3209 花神的数论题

    [数位dp] bzoj 3209 花神的数论题 题意:中文题. 思路:和普通数位dp一样,这里转换成二进制,然后记录有几个一. 统计的时候乘起来就好了. 代码: #include"cstdl ...

  8. bzoj3209:3209: 花神的数论题

    觉得还是数位dp的那种解题形式但是没有认真的想,一下子就看题解.其实还是设置状态转移.一定要多思考啊 f[i][j]=f[i-1][j]+g[i-1][j] g[i][j]=f[i-1][j-1]+g ...

  9. bzoj 3209: 花神的数论题 喵哈哈村的秘境探险(四)

    3209: 花神的数论题 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 2169  Solved: 1006 [Submit][Status][Di ...

最新文章

  1. Scrum看板工具Leangoo记录我的装修事件,hhhh
  2. 架空输电线路运行规程_[精品课程]绝缘子及其设计架空输电线路设计
  3. 史上最详细最容易理解的HMM文章
  4. comet 异步请求技术中相关关键字解释 (新手向)
  5. docker部署springboot应用
  6. 如何用软件工程消灭软件危机?
  7. hystrix 全局熔断_跟我学Spring Cloud(Finchley版)14Feign使用Hystrix
  8. php api 文档 管理,Api开发者福利之api在线管理,模拟请求测试,文档生成工具--Apizza...
  9. mp3文件怎么压缩大小
  10. 保险中介系列法规年内出台
  11. jQuery+Ajax+全解析
  12. 计算机专业该如何找实习工作?迷茫、不知所措的你值得一看~
  13. 数字图像处理 第八章 图像压缩
  14. error: src refspec dev does not match any.
  15. 云南大学计算机学院导师信息,云南大学软件学院研究生导师介绍:姚绍文(教授,博士生导师)...
  16. 读取excel批量生成二维码
  17. 怎么传文件到百度云服务器,别人传文件给我 可是怎么用百度网盘保存文件呢 其实很简单!...
  18. bug的生命周期你知道吗?一张图带你看懂它!
  19. Windows11下安装jdk
  20. PUTTY 中文教程

热门文章

  1. 计算机桌面老是弹出广告,桌面老是弹出广告怎么办? 爱问知识人
  2. 域用户和计算机上解锁用户的账户,AD域账户锁定时间
  3. url 保持不变php,thinkphp3.2.3如何只改变地址url中的某一个分隔符,其它保持不变...
  4. D - Yet Another Problem On a Subsequence CodeForces - 1000D (DP,组合数学)
  5. STS+Git 项目操作相关
  6. 关于jsp中jstl-core标签循环遍历的使用
  7. dubbo报错Data length too large: 10710120处理,及服务提供者协议配置详细说明
  8. Oracle 左连接、右连接、全外连接、(+)号作用
  9. 基于ARM 构架(带MMU)的copy_from_user与copy_to_user详细分析
  10. [WPF系列]Button 自定义