『最小表示法 Necklace』
<更新提示>
<第一次更新>
<正文>
最小表示法
这是一个简单的字符串算法,其解决的问题如下:
给定一个字符串\(S\),长度为\(n\),如果把它的最后一个字符不断放到最前面,会得到\(n\)个不同的字符串,那么我们称这\(n\)个字符串是循环同构的。这\(n\)个字符串中字典序最小的一个,我们就称为\(S\)的最小表示。
\(For\ example:\)
\(S=abcda,S_1=aabcd,S_2=daabc,S_3=cdaab,S_4=bcdaa\)
其中,\(S\)的最小表示为\(S_1\)。
了解了概念以后,我们将介绍一种算法,可以在\(O(n)\)的时间内求出一个字符串的最小表示。
对于一个环,最朴素的方法就是复制一倍接在原序列后面,这里我们就要用到这种方法:令字符串$$S'i=\begin{cases}1 \leq i\leq n ,S_i\n<i \leq 2n ,S{i-n}\end{cases}$$
然后,利用两个指针\(i,j\)扫描字符串\(S'\),其具体方法如下:
1.初始化\(i=1,j=2\)
2.直接向后扫描,比较两个循环同构串\(S'(i,i+n-1),S'(j,j+n-1)\)
2.(1) 如果扫描了\(n\)个字符两个串仍然相等,则说明这个字符串只由一个字符构成,任意位置开头都是最小表示
2.(2) 找到位置\(S'_{i+k} != S'_{j+k}\),若\(S'_{i+k} > S'_{j+k}\),则说明位置\(j\)更优,更新位置\(i=i+k+1\),若\(S'_{i+k} < S'_{j+k}\),则说明位置\(i\)更优,更新位置\(j=j+k+1\)
3.若\(i>n\),则说明位置\(j\)为最小表示,若\(j>n\),则说明位置\(i\)为最小表示
为什么\(S'_{i+k} > S'_{j+k}\)时,直接将\(i\)更新为\(i+k+1\)呢,相信这是最大的一个疑问。
\(Explain:\)
当\(S'_{i+k} > S'_{j+k}\)时,显然\(S'_i\)不是最小表示,因为存在一个更优的最小表示\(S'_j\)。然而,\(S'_{i+p}(1 \leq p \leq k)\)均不是最小表示,对于任意的一个\(S'_{i+p}\),一定也存在一个\(S'_{j+p}\)比它更优,因为它们不断向后比较,同样会在\(i+k\)处发现有\(S'_{i+k} > S'_{j+k}\)。这样就说明了当一个\(i\)在\(i+k\)的位置发现不优时,\(i+k\)以前的也均不优,直接将\(i\)更新为\(i+k+1\)即可。
同理,发现\(j\)不优时也是一样的。
\(Code:\)
inline void solve(void)
{
int ans;
int i=1,j=2,k;
while(i<=n&&j<=n)
{
for(k=0;k<=n&&s[i+k]==s[j+k];k++);
if(k==n)break;
if(a[i+k]>a[j+k])
{
i=i+k+1;
if(i==j)i++;
}
else
{
j=j+k+1;
if(i==j)j++;
}
}
ans=min(i,j);
}
Necklace
Description
有一天,袁同学绵了一条价值连城宝石项链,但是,一个严重的问题是,他竟然忘记了项链的主人是谁!在得知此事后,很多人向袁同学发来了很多邮件,都说项链是自己的,要求他归还(显然其中最多只有一个人说了真话)。袁同学要求每个人都写了一段关于自己项链的描述: 项链上的宝石用数字0至9来标示。一个对于项链的表示就是从项链的某个宝石开始,顺指针绕一圈,沿途记下经过的宝石,比如如下项链: 1-2-3-4
它的可能的四种表示是0123、1230、2301、3012。
袁☆同学现在心急如焚,于是他找到了你,希望你能够编一个程序,判断两个给定的描述是否代表同一个项链(注意,项链是不会翻转的)。
给定两个项链的表示,判断他们是否可能是一条项链。
Input Format
输入文件只有两行,每行一个由0至9组成的字符串,描述一个项链的表示(保证项链的长度是相等的)。
Output Format
如果两条项链不可能同构,那么输出’No’,否则的话,第一行输出一个’Yes’
第二行输出该项链的字典序最小的表示。 设L = 项链长度,L <= 1000000。
Sample Input
2234342423
2423223434
Sample Output
Yes
2234342423
解析
这就是一道最小表示法模板题,直接将两个串分别转为最小表示法,再比较是否相同即可。如果相同,直接将最小表示法输出。
\(Code:\)
#include<bits/stdc++.h>
using namespace std;
const int N=1000000+20;
int lena,lenb;
char a[N*2],b[N*2],Mina[N],Minb[N];
inline void input(void)
{
scanf("%s",a+1);
scanf("%s",b+1);
lena=strlen(a+1);
lenb=strlen(b+1);
for(int i=1;i<=lena;i++)
a[lena+i]=a[i];
for(int i=1;i<=lenb;i++)
b[lenb+i]=b[i];
}
inline void solvea(void)
{
int ans;
int i=1,j=2,k;
while(i<=lena&&j<=lena)
{
for(k=0;k<=lena&&a[i+k]==a[j+k];k++);
if(k==lena)break;
if(a[i+k]>a[j+k])
{
i=i+k+1;
if(i==j)i++;
}
else
{
j=j+k+1;
if(i==j)j++;
}
}
ans=min(i,j);
for(int p=1;p<=lena;p++)
Mina[p]=a[ans+p-1];
}
inline void solveb(void)
{
int ans;
int i=1,j=2,k;
while(i<=lenb&&j<=lenb)
{
for(k=0;k<=lenb&&b[i+k]==b[j+k];k++);
if(k==lenb)break;
if(b[i+k]>b[j+k])
{
i=i+k+1;
if(i==j)i++;
}
else
{
j=j+k+1;
if(i==j)j++;
}
}
ans=min(i,j);
for(int p=1;p<=lenb;p++)
Minb[p]=b[ans+p-1];
}
int main()
{
input();
solvea();
solveb();
int flag=1;
if(lena!=lenb)
{
printf("No\n");
return 0;
}
for(int i=1;i<=lena;i++)
if(Mina[i]^Minb[i])flag=0;
if(!flag)
{
printf("No\n");
return 0;
}
else
{
printf("Yes\n");
for(int i=1;i<=lena;i++)
printf("%c",Mina[i]);
puts("");
}
return 0;
}
<后记>
『最小表示法 Necklace』的更多相关文章
- 『Tree nesting 树形状压dp 最小表示法』
Tree nesting (CF762F) Description 有两个树 S.T,问 S 中有多少个互不相同的连通子图与 T 同构.由于答案 可能会很大,请输出答案模 1000000007 后的值 ...
- 【BZOJ 1398】 1398: Vijos1382寻找主人 Necklace (最小表示法)
1398: Vijos1382寻找主人 Necklace Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 308 Solved: 129 Descrip ...
- BZOJ1398Vijos1382寻找主人 Necklace——最小表示法
题目描述 给定两个项链的表示,判断他们是否可能是一条项链. 输入 输入文件只有两行,每行一个由0至9组成的字符串,描述一个项链的表示(保证项链的长度是相等的). 输出 如果两条项链不可能同构,那么输出 ...
- BZOJ1398: Vijos1382寻找主人 Necklace 字符串最小表示法
Description 给定两个项链的表示,判断他们是否可能是一条项链. Input 输入文件只有两行,每行一个由0至9组成的字符串,描述一个项链的表示(保证项链的长度是相等的). Output 如果 ...
- 初涉最小表示法&&bzoj1398: Vijos1382寻找主人 Necklace
把最小表示法的坑填了 Description 给定两个项链的表示,判断他们是否可能是一条项链. Input 输入文件只有两行,每行一个由0至9组成的字符串,描述一个项链的表示(保证项链的长度是相等的) ...
- [bzoj 1398] Vijos1382寻找主人 Necklace 解题报告(最小表示法)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1398 题目: Description 给定两个项链的表示,判断他们是否可能是一条项链. ...
- BZOJ 1398: Vijos1382寻找主人 Necklace(最小表示法)
传送门 解题思路 最小表示法.首先对于判断是不是循环同构的串,直接扫一遍用哈希判即可.然后要输出字典序最小的就要用到最小表示法,首先可以把串复制一遍,这样的话就可以把串变成静态操作.如果对于两个位置\ ...
- 【阿里云产品公测】以开发者角度看ACE服务『ACE应用构建指南』
作者:阿里云用户mr_wid ,z)NKt# @I6A9do 如果感觉该评测对您有所帮助, 欢迎投票给本文: UO<claV RsfTUb)< 投票标题: 28.[阿里云 ...
- POJ1509 Glass Beads(最小表示法 后缀自动机)
Time Limit: 3000MS Memory Limit: 10000K Total Submissions: 4901 Accepted: 2765 Description Once ...
随机推荐
- git使用命令讲解
1.创建版本库 ①选择一个合适的地方,创建一个空目录 mkdir learngit cd learngit ②通过git init命令把这个目录变成Git可以管理的仓库: git init Git ...
- 部分手机浏览器存在将ajax请求当成广告过滤的情况,及解决方案
我们发现h5页面在某些浏览器请求不到数据,经过排查,是浏览器的广告拦截模块搞的鬼. 通过删减参数,发现adtype和adnum参数去掉后,接口可以正常请求,开始以为是官方拦截关键词带有ad的参数,后来 ...
- 感动到哭的SBT下载
在centos上搭建spark开发环境.使用IntelliJ IDEA做scala开发,需要配置SBT.一直卡在从maven上下载jar包的过程中,还几次都下失败了.试过vpn也没有用. 还好偶然看到 ...
- FunData — 电竞大数据系统架构演进
电竞出现在人们视野中的频率越来越高了,此次选取FunData作为电竞数据平台,v1.0 beta版本主要提供由Valve公司出品的顶级MOBA类游戏DOTA2相关数据接口(详情:open.varena ...
- Shell脚本学习 - 基本内容以及数据格式
为了捞取日志,自己用python写了一些东西,大致套路就是读取写入文件的操作,放到linux上跑.实际使用时发现要操作的文件有时比较大,直接打开文件找需要的东西可能会有一些效率问题.所以学习一下she ...
- [转]HTML5 script 标签的 crossorigin 属性到底有什么用?
HTML5 script 标签的 crossorigin 属性到底有什么用? 最近Bootstrap 4已经正式发布了,可能已经有爱尝鲜的小伙伴在 alpha 阶段就尝试过 BS4.不过今天要说的不是 ...
- C语言柔性数组讲解
#include<stdio.h> typedef struct _SoftArray{ int len; int array[]; }SoftArray; int main() { ; ...
- 信息学奥赛辅导经验谈 & 问题教学法中的学生思维能力培养
转载来自朱全民名师工作室 信息学奥赛辅导经验谈 全国青少年信息学奥林匹克分区竞赛(简称NOI)是经中国科协.国家教育部批准,由中国计算机学会主办的一项全国性的青少年学科竞赛活动.随着信息学奥林匹克竞赛 ...
- 关于阿里ICON矢量图(SVG)上传问题.
注意点: 1. 存储为svg格式(建议使用存储为svg,不要使用导出为svg)2. 图像位置:链接(注意哦,不要点嵌入和保留编辑功能)---确定3. AI里面选中图形,点对象-路径-轮廓化描边 软件编 ...
- 字符串转义为HTML
有时候后台返回的数据中有字符串,并需要将字符串转化为HTML,下面封装了一个方法,如下 // html转义 function htmlspecialchars_decode(string, quote ...