https://konnyakuxzy.github.io/BZPRO/JudgeOnline/2740.html

题解讲的很清楚了

(好像等于的情况应该归入case2而不是case1?并不确定)

具体方法:

将串翻转,找到字典序最小且最短的后缀,然后找到以这个后缀为纯循环节的最长后缀T,则第一步是将这个后缀T提到最前面;

然后第二步是把整个串除T外部分变为其循环同构串的最小表示。

要找到字典序最小且最短的后缀,只要找到整个串的最小表示法(设最小表示法在位置i开始),然后找到S[i..n]的最短公共前后缀即可(容易发现是对的)(见代码1);也可以直接用最小表示法类似的方法一次直接求出来(见代码2)

代码1:

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii; int T;
char s[];
int f[];
int calc(const char *s,int n)
{
int i=,j=,k=,t;
while(i<n&&j<n&&k<n)
{
t=s[(i+k)%n]-s[(j+k)%n];
if(t==) ++k;
else
{
if(t>) i+=k+;
else j+=k+;
if(i==j) ++j;
k=;
}
}
return min(i,j);
}
int n;
int an1,an2;
int main()
{
int i,j,t;
scanf("%d",&T);
while(T--)
{
scanf("%s",s);n=strlen(s);
reverse(s,s+n);
t=calc(s,n);
//printf("1t%d\n",t);
//t=0;
f[t]=;
for(i=t+,j=;i<n;++i)
{
//j=f[i-1];
while(j>&&s[t+j]!=s[i]) j=f[t+j-];
//printf("2t%d %c %c\n",j,s[t+j],s[i]);
if(s[t+j]==s[i]) ++j;
//printf("1t%d %d %d\n",i,t+j,s[t+j]==s[i]);
f[i]=j;
}
//for(i=t;i<n;++i) printf("%d %d\n",i,f[i]);
j=f[n-];
if(j)
{
while(f[t+j-]>) j=f[t+j-];
t=n-j;
}
//printf("1t%d\n",t);
for(j=t;;)
{
//printf("3t%d %d\n",j-(n-t),t);
if(j>=n-t&&strncmp(s+(j-(n-t)),s+t,n-t)==)
j-=n-t;
else
break;
}
t=j;
//printf("2t%d\n",t);
an1=n-t;
//printf("%d\n",an1);
//printf("%d\n",t);
t=calc(s,t);
an2=n-t;
printf("%d %d\n",an1,an2);
}
return ;
}

代码2:(话说这个复杂度真的对吗?不确定啊?不过实测全a串还有一些随机的串的确是O(n)的,并且能A掉题)

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
int T;
char s[];
//int f[10000100];
int calc(const char *s,int n)
{
int i=,j=,k=,t;
while(i<n&&j<n&&k<n)
{
t=s[(i+k)%n]-s[(j+k)%n];
if(t==) ++k;
else
{
if(t>) i+=k+;
else j+=k+;
if(i==j) ++j;
k=;
}
}
return min(i,j);
}
int n;
int an1,an2;
int main()
{
int i,j,k,t;
scanf("%d",&T);
while(T--)
{
scanf("%s",s);
n=strlen(s);
reverse(s,s+n);
i=;j=;k=;
//int tt=0;
while(i<n&&j<n&&k<n)
{
//++tt;
//printf("1t%d %d %d\n",i,j,k);
t=((i+k<n)?s[i+k]:)-((j+k<n)?s[j+k]:);
if(t==) ++k;
else
{
if(t>) i+=(j+k<n)?k+:k;
else j+=(i+k<n)?k+:k;
if(i==j) ++j;
k=;
}
}
//printf("1t%d\n",tt);
t=min(i,j);
for(j=t;;)
{
if(j>=n-t&&strncmp(s+(j-(n-t)),s+t,n-t)==)
j-=n-t;
else
break;
}
t=j;
an1=n-t;
t=calc(s,t);
an2=n-t;
printf("%d %d\n",an1,an2);
}
return ;
}

https://konnyakuxzy.github.io/BZPRO/JudgeOnline/2176.html

最小表示法板子

题解

这题数据范围比较诡异,一定要用unsigned char。。。

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
unsigned char s[];
int calc(const unsigned char *s,int n)
{
int i=,j=,k=,t;
while(i<n&&j<n&&k<n)
{
t=s[(i+k)%n]-s[(j+k)%n];
if(t==) ++k;
else
{
if(t>) i+=k+;
else j+=k+;
if(i==j) ++j;
k=;
}
}
return min(i,j);
}
int n;
int main()
{
int t;
scanf("%d%s",&n,s);
t=calc(s,n);
printf("%s",s+t);
s[t]=;
printf("%s",s);
return ;
}

bzoj2740 串 && bzoj2176 strange string(最小表示法模板)的更多相关文章

  1. BZOJ 2176 Strange string 最小表示法

    题目大意:给定一个串S,求最小表示法 n<=1000W,实在不敢写后缀自己主动机,就去学了最小表示法= = 记得用unsigned char不然WA= = 数据真是逗- - #include & ...

  2. BZOJ 2176 Strange string ——最小表示法

    本来想用来练习后缀自动机的,但是100w有点虚(事实证明确实T掉了). 只好上最小表示法. #include <cstdio> #include <cstring> #incl ...

  3. BZOJ2176Strange string——最小表示法

    题目描述 给定一个字符串S = {S1, S2, S3 … Sn}, 如果在串SS中, 子串T(|T| = n)为所有长度为n的SS的字串中最小的(字符串的比较), 则称T为”奇怪的字串”. 你的任务 ...

  4. Manacher模板,kmp,扩展kmp,最小表示法模板

    *N]; //储存临时串 *N];//中间记录 int Manacher(char tmp[]) { int len=strlen(tmp); ; ;i<len;i++) { s[cnt++]= ...

  5. bzoj2176 Strange string(字符串最小表示法)

    Time Limit: 10 Sec  Memory Limit: 259 MB 给定一个字符串S = {S1, S2, S3 … Sn}, 如果在串SS中, 子串T(|T| = n)为所有长度为n的 ...

  6. HDU3374 字符串最大最小表示法模板

    一开始没太看懂什么意思,拿笔反复推了一遍才大概知道最大最小表示法是怎么求的,感觉太神奇了... #include <iostream> #include <cstdio> #i ...

  7. 最小标示法模板 poj1509

    最小标示法:给定一个字符串,不断将其最后一个字符放到开头,最终会得到n个字符串,称这n个字符串循环同构,这些字符串中字典序最小的一个,就是最小表示法 #include<iostream> ...

  8. [USACO5.5]隐藏口令Hidden Password [最小表示法模板]

    最小表示法就是一个字符串构成一个环,找以哪个点为开头字典序最小. 然后我们就可以用n2的算法愉快的做啦~实际上有O(n)的做法的,就是用两个指针扫,如果这两个位置的字典序相等,就一起往后,如果某一个大 ...

  9. HDU - 3374:String Problem (最小表示法模板题)

    Give you a string with length N, you can generate N strings by left shifts. For example let consider ...

随机推荐

  1. CSS3学习笔记(2)—左右跳动的红心

    还在为无法表达内心澎湃的心情而着急吗?还在为制作跳动的心而烦恼吗?哈哈,今天我就把代码全部奉上,为你们追妹子添点贡献,下面来看最终的动态效果(事先说明一下:我用的截屏gif制作软件是绿色版的,所以gi ...

  2. Gym - 100283F F. Bakkar In The Army —— 二分

    题目链接:http://codeforces.com/gym/100283/problem/F F. Bakkar In The Army time limit per test 2 seconds ...

  3. div遮罩弹框口

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  4. AJAX 方式

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. centos7使用ceph-deploy部署ceph

    准备阶段 准备yum源 删除默认的源,国外的比较慢 yum clean all rm -rf /etc/yum.repos.d/*.repo 下载阿里云的base源 wget -O /etc/yum. ...

  6. 二维码扫描极速版2.0.apk

    二维码扫描极速版2.0.apk 百度网盘下载地址: http://pan.baidu.com/s/1o686bGI 二维码扫描极速版 描述 二维码扫描极速版,快速识别二维码中的信息. 简单易用. 提高 ...

  7. JS正则表达式(一)

    正则表达常用符号 /..../  开始结束 ^ 开始 $ 结束 /s 任何非空字符  /S 非空 /d  匹配一个数字=[0-9] /D  匹配一个非数字=[^0-9] /w   匹配一个数字,下划线 ...

  8. 评判云服务靠谱程度 -- Coding 安全那些事

    本文依据孙宇聪在 SegmentFault D-Day 北京场的演讲内容整理,并授权首发于“高效运维”公众号.10月11日,SegmentFault 将在上海举办D-Day,围绕 Docker 主题. ...

  9. 2.12 Hivet中order by,sort by、distribute by和cluster by

    https://cwiki.apache.org/confluence/display/Hive/LanguageManual+SortBy 一.order by 对全局数据的排序,仅仅只有一个red ...

  10. c++中stl----vector

    1 vector是啥玩意 (1)可以使用下标访问个别的元素 (2)迭代器可以按照不同的方式遍历 (3)可以在容器的末尾增加或者删除元素 2 容器大小和容器的容量区别 (1)大小是元素的个数,容量是分配 ...