Codeforces 109D String Transformation 字符串 哈希 KMP
原文链接https://www.cnblogs.com/zhouzhendong/p/CF109D.html
题目传送门 - CF109D
题意
给定两个字符串 $a,b$ ,求一组 $i,j$ 使得 $f(a,i,j)=b$ 。如果无解输出 "-1 -1" ,如果多组解,输出 i 尽量大的;如果 i 相同,输出 j 尽量小的。
其中 $f(s,i,j) = s[i+1 \cdots j-1] + r(s[0 \cdots i]) + r(s[j\cdots n-1])$ 。 $n$ 为串长。其中 $s[i\cdots j]$ 表示 串 $s$ 的 $i$ 至 $j$ 个位置构成的子串,+ 运算定义为字符串顺序拼接,$r(s)$ 表示 $s$ 翻转后得到的串。
$|a|,|b| \leq 10^6$
题解
那个最大最小问题不大,我们来看看如何找一组解。
首先,讲 a 串翻转。则问题变成了 $r(a[i+1]\cdots a[j-1])+a[0\cdots i] + a[j\cdots n-1]=b$ 的 $(i,j)$ 。这个问题,只需要枚举 $j$ ,然后判定是否可以行即可。
对于 $r(a[i+1]\cdots a[j-1])$ 与 $b$ 的最大匹配长度,可以二分 + 哈希。
对于以 b 串第 $j-1$ 个位置结尾的子串中与 $a$ 的前缀的匹配长度最大为多少,直接 KMP 。
如果这两个长度大于 $j-1$ ,那么就可行。
那个什么最大最小的,随便弄一弄就好了。
注意我们求出来的翻转后的 a 串的答案,最后还要变换一下。
代码
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
const int N=1000005*2;
char a[N],b[N];
int n,Next[N],len[N];
ULL Ha[N],Hb[N],Fac[N],T=233;
ULL Get_Hash(ULL *Ha,int L,int R){
if (L>R)
L=n*2-L+1,R=n*2-R+1;
return Ha[R]-Ha[L-1]*Fac[R-L+1];
}
void KMP(char *a,char *b,int n){
for (int i=2,k=0;i<=n;Next[i]=k+=(a[k+1]==a[i]),i++)
while (k>0&&a[k+1]!=a[i])
k=Next[k];
for (int i=1,k=0;i<=n;len[i]=k+=(a[k+1]==b[i]),i++)
while (k>0&&a[k+1]!=b[i])
k=Next[k];
}
int Get(int j){
int L=1,R=j-1,mid,k1=0;
while (L<=R){
mid=(L+R)>>1;
if (Get_Hash(Hb,1,mid)==Get_Hash(Ha,j-1,j-mid))
L=mid+1,k1=mid;
else
R=mid-1;
}
return k1+len[j-1]<j-1?-1:len[j-1];
}
int main(){
gets(a+1),gets(b+1);
n=strlen(a+1);
if (strlen(b+1)!=n)
return puts("-1 -1"),0;
reverse(a+1,a+n+1);
for (int i=n+1;i<=n*2;i++)
a[i]=a[n*2-i+1],b[i]=b[n*2-i+1];
KMP(a,b,n);
for (int i=Fac[0]=1;i<=n*2;i++){
Fac[i]=Fac[i-1]*T;
Ha[i]=Ha[i-1]*T+a[i];
Hb[i]=Hb[i-1]*T+b[i];
}
int ansi=10000000,ansj=10000000,d=-1;
for (d=n;d>1;d--)
if (a[d]!=b[d])
break;
for (int i=-1,j=d+1;j<=n&&!~i;j++)
if (~(i=Get(j)))
ansi=i,ansj=j;
if (ansj==10000000)
ansi=ansj=-1;
else
ansi=n-ansi,ansj=n-ansj;
printf("%d %d\n",ansj,ansi);
return 0;
}
Codeforces 109D String Transformation 字符串 哈希 KMP的更多相关文章
- 牛客练习赛33 E tokitsukaze and Similar String (字符串哈希hash)
链接:https://ac.nowcoder.com/acm/contest/308/E 来源:牛客网 tokitsukaze and Similar String 时间限制:C/C++ 2秒,其他语 ...
- 牛客练习赛33 E. tokitsukaze and Similar String (字符串哈希)
题目链接:https://ac.nowcoder.com/acm/contest/308/E 题意:中文题 见链接 题解:哈希预处理(三哈希模板) #include <bits/stdc++.h ...
- - Power Strings (字符串哈希) (KMP)
https://www.cnblogs.com/widsom/p/8058358.htm (详细解释) //#include<bits/stdc++.h> #include<vect ...
- Codeforces 1383C - String Transformation 2(找性质+状压 dp)
Codeforces 题面传送门 & 洛谷题面传送门 神奇的强迫症效应,一场只要 AC 了 A.B.D.E.F,就一定会把 C 补掉( 感觉这个 C 难度比 D 难度高啊-- 首先考虑对问题进 ...
- UVA - 11475 Extend to Palindrome —— 字符串哈希 or KMP or 后缀数组
题目链接:https://vjudge.net/problem/UVA-11475 题意: 给出一个字符串,问在该字符串后面至少添加几个字符,使得其成为回文串,并输出该回文串. 题解: 实际上是求该字 ...
- Redis支持的数据类型及相应操作命令:String(字符串),Hash(哈希),List(列表),Set(集合)及zset(sorted set:有序集合)
help 命令,3种形式: help 命令 形式 help @<group> 比如:help @generic.help @string.help @hash.help @list.hel ...
- Codeforces Round #543 (Div. 2) F dp + 二分 + 字符串哈希
https://codeforces.com/contest/1121/problem/F 题意 给你一个有n(<=5000)个字符的串,有两种压缩字符的方法: 1. 压缩单一字符,代价为a 2 ...
- 【CodeForces】961 F. k-substrings 字符串哈希+二分
[题目]F. k-substrings [题意]给定长度为n的串S,对于S的每个k-子串$s_ks_{k+1}...s_{n-k+1},k\in[1,\left \lceil \frac{n}{2} ...
- PAT 甲级 1047 Student List for Course (25 分)(cout超时,string scanf printf注意点,字符串哈希反哈希)
1047 Student List for Course (25 分) Zhejiang University has 40,000 students and provides 2,500 cou ...
随机推荐
- Tornado学习笔记(一) helloword/多进程/启动参数
前言 当你觉得你过得很舒服的时候,你肯定没有在进步.所以我想学习新的东西,然后选择了Tornado.因为我觉得Tornado更匹配目前的我的综合素质. Tornado学习笔记系列主要参考<int ...
- Web框架之Bootstrap
一.Bootstrap简介 Bootstrap,来自Twitter的设计师Mark Otto和Jacob Thornton合作开发,是目前很受欢迎的Web前端开源框架. Bootstrap 是基于HT ...
- Confluence 6 配置 Windows 服务
当你使用 Start Confluence Automatically on Windows as a Service 的方式启动的时候,你有下面 2 种方式来配置你的系统属性:通过 command ...
- vue的多选框
- gnuradio 创建cos_source
C++教程 ys_linux@computer:~$ gr_modtool nm kcd Creating out-of-tree module in ./gr-kcd... Done. Use 'g ...
- Linux下vsftpd的安装,Java上传文件实现。
首先我们需要查看是否已经安装vsftpd,输入命令 :vsftpd -v.如果出现以下信息,那么就说明已经安装vsftpd 如果没有安装,那么输入命令 : yum install vsftpd ...
- java多线程机制中的Thread和Runnable()区别
1.java语言使用Thread类及其子类对象来表示线程,新建的一个线程声明周期中经历 新建.(声明一个线程,此时他已经有了相应的内存空间和其他资源),运行(线程创建之久就据用了运行的条件,一旦轮到使 ...
- bzoj 2150
然后考虑正解 我们发现,最坏情况就是每个点都派驻军队,所以答案至多是“.”的数目 而且,每个点都至多只有一个入度和一个出度,所以我们可以将每个点拆成两个点,一个作为入点,一个作为出点,然后所有图上能到 ...
- Java面向对象(二)
一.封装 1.为什么要使用封装在类的外部直接操作类的属性是”不安全的"2.如何实现封装 1).属性私有化:设置属性的修饰符为private 2) .提供公共的set和get方法赋值 ...
- 用 DocumentFormat.OpenXml 和Microsoft.Office.Interop.Word 写入或者读取word文件
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Tex ...