FJUT-这还是一道数论题
这还是一道数论题
最后来个字符串签个到吧,这题其实并不难,所需的算法比较基础,甚至你们最近还上过课。
为了降低难度,免得所有人爆零。这里给几个提示的关键字 :字符串,回文,二分,哈希. 注意要对奇偶回文分开二分
这样还不会做,说明基础有所欠缺。
给你一个字符串A和一个字符串B,请你求一个满足以下要求的所有字符串中,最长的字符串C的长度:
C必须同时是A和B的子串,即A和B中都必须存在一个子区间和C长得一样
C必须是一个回文,即正过来读和反过来读都一样
多组数据,请处理到EOF
每组数据包含,两行,每行都是仅由小写字符构成的字符串,代表A和B。
对于30%的数据。
保证|A|,|B|<=1000,且单个文件的字符总数小于10000
对于100%的数据
保证|A|,|B|<=100000,且单个文件的字符总数小于2e6
其中70%的数据答案为奇数哦
因为没有处理掉字符串尾巴上多余的'\r',所以为了防止读到'\r' 推荐使用scanf("%s");
输出C的长度
bbabbbcbcbbbddde
bbbabbbccadddbbba
dggdgzz
dggdbb
aaa
bbb
acbdbca
bcadacb
5
4
0
1
hint:
对于第一个数据C取bbabb
对于第二个数据C取dggd 用马拉车预处理,这样可以O(1)判断任意区间是否是回文。 然后就是用二分答案的长度,用哈希O(n)计算是否有长度为len的公
共回文子串,注意。 二分时奇偶回文要分开二分。因为如何有2k+2长度的公共回文。肯定也会有2k长度的公共回文,但是不保证也
有2k+1的长度的公共回文。。数据里70%的答案是奇的。所以你只二分奇数长度即可得到70分. 如果不想奇偶分开讨论的话,可以用马拉车的技巧,转化为全部都是奇回文
细节在代码中有解释
#include<bits/stdc++.h>
typedef unsigned long long ull;
const int maxn=100005;
const ull P=131;
using namespace std;
char str1[maxn],str2[maxn];
ull f1[maxn],f2[maxn],p[maxn];
int len1,len2,tmp_len;
int len[maxn<<1];
char tmp[maxn<<1];
void init()
{
p[0]=1;
for(int i=1; i<maxn; i++)
{
p[i]=p[i-1]*P;
}
}
ull Hash(ull f[],int l,int r)
{
return f[r+1]-f[l]*p[r-l+1];
} void GetHash(char str[],ull f[])
{
int len_str=strlen(str);
f[0]=0;
for(int i=0; i<len_str; i++)
f[i+1]=f[i]*P+str[i];
}
int manachar_init(char st[])
{
int i,str_len=strlen(st);
tmp[0]='@';///加一个特殊字符,防止越界
for(int i = 1; i <= 2*str_len ; i+=2)
{
tmp[i]='#';
tmp[i+1]=st[i/2];
}
tmp[2*str_len+1]='#';
tmp[2*str_len+2]='$';///字符串结尾加一个字符,防止越界
return 2*str_len+1;///返回转换字符串的长度
}
void manachar(char st[],int str_len)
{
int p_mx=0,ans=0,po=0;///p_mx即为“当前”计算回文串最右边字符的最大值,po为当前该回文字符串的中心
for(int i=1;i<=str_len;i++)
{
if(i<p_mx)
len[i]=min(p_mx-i,len[2*po-i]);///po对应最大回文子串中心点的位置
else
len[i]=1;
while(st[i-len[i]]==st[i+len[i]])
len[i]++;
if(len[i]+i>p_mx)
{
po=i;
p_mx=i+len[i];
}
ans=max(ans,len[i]);
}
}
map< ull,int >mp;
bool cheak(int m)
{
mp.clear();
for(int i=0; str1[i+m-1]; i++)
{
if(len[i+i+m+1]-1>=m)///i+i+m+1对应原回文子字符串str[i~(i+m-1)]在转换后字符串的回文中心位置(l+r+2)
{
ull cnt=Hash(f1,i,i+m-1);
mp[cnt]=i;///记录该回文串的起点
}
}
for(int i=0; str2[i+m-1]; i++) ///枚举第二个字符串的起点
{
ull cnt=Hash(f2,i,i+m-1);
if(mp.count(cnt))
{
int po=mp[cnt];///po为在str1中的起点
int j=0;
for( j=0; j<m; j++)///判断这两个字符串是否相等
{
if(str1[po+j]!=str2[i+j])
break;
}
if(j>=m)
return true;
}
}
return false;
}
int main()
{
init();
while(scanf("%s %s",str1,str2)!=EOF)
{
int ans=0;
GetHash(str1,f1);
GetHash(str2,f2);
len1=strlen(str1);
len2=strlen(str2);
tmp_len=manachar_init(str1);
///tmp为转换后的字符串 tmp_len该字符串长度
manachar(tmp,tmp_len);
int l=0,r=min(len1,len2)/2+1;
while(l+1<r)
{
int mid=(l+r)/2;
if(cheak(mid*2))
{
l=mid;
}
else
{
r=mid;
}
}
ans=max(ans,l*2);
l=l-1,r=min(len1,len2)/2+1;
while(l+1<r)
{
int mid=(l+r)/2;
if(cheak(mid*2+1))
{
l=mid;
}
else
{
r=mid;
}
}
ans=max(ans,l*2+1);
printf("%d\n",ans);
}
return 0;
}
FJUT-这还是一道数论题的更多相关文章
- FJUT3701 这也是一道数论题(线段树)题解
Problem Description 好久没出数据结构题,现在赶紧来做道数据结构题热热身 小q现在要去银行,他有个很厉害的bug能看到前面排队的人.假如当前有人正在办理业务,那么肯定要等待前一个人完 ...
- FJUT3703 这还是一道数论题(二分 + hash + manacher 或者 STL + hash 或者 后缀数组 + hash)题解
Problem Description 最后来个字符串签个到吧,这题其实并不难,所需的算法比较基础,甚至你们最近还上过课. 为了降低难度,免得所有人爆零.这里给几个提示的关键字 :字符串,回文,二分, ...
- fjutacm 3700 这是一道数论题 : dijkstra O(mlogn) 二进制分类 O(k) 总复杂度 O(k * m * logn)
/** problem: http://www.fjutacm.com/Problem.jsp?pid=3700 按二进制将k个待查点分类分别跑dijkstra **/ #include<std ...
- BZOJ 3209: 花神的数论题 [数位DP]
3209: 花神的数论题 题意:求\(1到n\le 10^{15}\)二进制1的个数的乘积,取模1e7+7 二进制最多50位,我们统计每种1的个数的数的个数,快速幂再乘起来就行了 裸数位DP..\(f ...
- 【洛谷】4317:花神的数论题【数位DP】
P4317 花神的数论题 题目背景 众所周知,花神多年来凭借无边的神力狂虐各大 OJ.OI.CF.TC …… 当然也包括 CH 啦. 题目描述 话说花神这天又来讲课了.课后照例有超级难的神题啦…… 我 ...
- 【LG4317】花神的数论题
[LG4317]花神的数论题 题面 洛谷 题解 设\(f_{i,up,tmp,d}\)表示当前在第\(i\)位,是否卡上界,有\(tmp\)个一,目标是几个一的方案数 最后将所有\(d\)固定,套数位 ...
- BZOJ3209 花神的数论题 【组合数学+数位DP+快速幂】*
BZOJ3209 花神的数论题 Description 背景 众所周知,花神多年来凭借无边的神力狂虐各大 OJ.OI.CF.TC …… 当然也包括 CH 啦. 描述 话说花神这天又来讲课了.课后照例有 ...
- [BZOJ3209]花神的数论题 组合数+快速幂
3209: 花神的数论题 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2498 Solved: 1129[Submit][Status][Disc ...
- 【BZOJ3209】花神的数论题 数位DP
[BZOJ3209]花神的数论题 Description 背景众所周知,花神多年来凭借无边的神力狂虐各大 OJ.OI.CF.TC …… 当然也包括 CH 啦.描述话说花神这天又来讲课了.课后照例有超级 ...
随机推荐
- 【刷题】【LeetCode】000-十大经典排序算法
[刷题][LeetCode]总 用动画的形式呈现解LeetCode题目的思路 参考链接 000-十大经典排序算法
- CentOS7切换源
1.备份 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 2.下载新的CentOS-Base ...
- easyui判断下拉列表
{field:'state',title:'状态',width:100, formatter : function(value, row, index){ if (value == 0) { retu ...
- CTFcracktools——非常实用的CTF解密工具
做bugku的crypto题时偶然发现了这个,吐血推荐!! 十分全面好用 整合了常见的解码.进制转换等CTF常用的工具: 下载地址: https://github.com/0Linchen/CTFCr ...
- 动态强制改变for循环里面item的值
var item = that.data.articles[inde_x]//获取数据列表 item.is_collection = 1//希望将特定的值改变 console.log(that.dat ...
- access数据库转sql server中ID的问题
USE [Task] GO /****** Object: Table [dbo].[Task] Script Date: 04/16/2018 16:14:56 ******/ SET ANSI_N ...
- MT【326】曲线中的爱恨情仇
[我思故我在]----笛卡尔爱心曲线$r=a(1-sin\theta)$ Matrix 67分手曲线
- 「LibreOJ β Round #4」框架 [bitset]
题面 loj #include <cmath> #include <cstring> #include <cstdio> #include <cstdlib& ...
- JDK源码分析(8) StringBuffer & StringBuilder
简介 StringBuffer与StringBuilder是两个常用的操作字符串的类.大家都知道,StringBuilder是线程不安全的,而StringBuffer是线程安全的.前者是JDK1.5加 ...
- 运行adb命令报错adb server version (31) doesn't match this client (39); killing...
执行adb devices 报错 原因分析: 这个是socket 的端口被占用了,我这里是因为360手机助手占用了这个端口,所以其他的就不能够用了. 解决办法: 卸载了360的手机助手就可以了 首先 ...