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. Python类的特殊属性

    Python中的特殊属性 定义如下类: class Foo(object): """Foo class definition""" 类的特殊 ...

  2. Android系统shell中的clear命令实现【转】

    本文转载自:http://blog.csdn.net/morixinguan/article/details/73467845 之前一直不太清楚,当我们在shell命令行输入很多命令,会在屏幕上输出一 ...

  3. 我在面试.NET/C#程序员时会提出的问题

    我在面试.NET/C#程序员时会提出的问题 2011-03-03 15:38 by 老赵, 28107 visits 说起来我也面试过相当数量的.NET(包括C#,后文不重复)程序员了,有的通过电话, ...

  4. 关于URL编码的一些结论

    转载自:http://www.ruanyifeng.com/blog/2010/02/url_encoding.html与http://www.ruanyifeng.com/blog/2007/10/ ...

  5. docker安装mysql挂载宿主本地目录资源后无法启动的问题

    可能是权限问题,添加--privileged=true参数: docker run -p : --name zsmysql -v $PWD/data:/var/lib/mysql -v $PWD/lo ...

  6. 为什要使用预编译SQL?

    今天在研发部技术大牛的指点下,我终于明白了为什么要使用SQL预编译的形式执行数据库JDBC:

  7. hdu-5621 KK's Point(dp+数学)

    题目链接: KK's Point Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Others ...

  8. Linux命令学习笔记- vmstat命令实战详解

    vmstat命令是最常见的Linux/Unix监控工具,可以展现给定时间间隔的服务器的状态值,包括服务器的CPU使用率,内存使用,虚拟内存交换情况,IO读写情况.这个命令是我查看Linux/Unix最 ...

  9. BZOJ_2730_ [HNOI2012]矿场搭建_点双联通分量

    BZOJ_2730_ [HNOI2012]矿场搭建_点双联通分量 Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路 ...

  10. 无向图hash

    一个效果还行的 无向图hash判同构的方法 求出每个点向其它点的最短路,然后排序,然后按字符串拼接起来,再按每个点的字符串 排序后的rank 作为每一个点的初始hash值 然后每一轮,把每个点的相邻点 ...