Hdu 5442 Favorite Donut (2015 ACM/ICPC Asia Regional Changchun Online 最大最小表示法 + KMP)
2024-09-07 09:42:13
题目链接:
题目描述:
给出一个文本串,找出顺时针或者逆时针循环旋转后,字典序最大的那个字符串,字典序最大的字符串如果有多个,就输出下标最小的那个,如果顺时针和逆时针的起始下标相同,则输出顺时针。
解题思路:
看到题目感觉后缀数组可以搞,正准备犯傻被队友拦下了,听队友解释一番,果断丢锅给队友。赛后试了一下后缀数组果然麻烦的不要不要的(QWQ),还是最大最小表示法 + KMP来的干净利索。
最大表示法:对于一个长度为len文本串,经过循环旋转得到长度为len的新串,新串是所有循环旋转得到的串中字典序最大的。
实现方法:对于文本串s,我们可以设定两个指针i, j.
刚开始的时候i = 0, j = 1;
当s[i] == s[j]时, (设定指针k) 从i, j 开始比较,直到s[i+k]!= s[j+k];
如果s[i+k] < s[j+k], i += k + 1, k = 0;
因为s[i+k] < s[j+k],证明以i开头的串已经没有意义,以i开头的串一定小于以j开头的串的字典序,所以把指针i移动到(i+k+1)的位置继续和以j开头的串比较;
依此得, j += k + 1, k = 0, 当前j 为最大表示串的起始点;
最后返回min(i, j)即可。(最小表示法把上面的大于改成小于就ok!)
代码实现:
int Max_Repre (char s[], int n)
{
int i = , j = , k = ;
while (i<n && j<n && k<n)
{
int nu = s[(i+k)%n] - s[(j+k)%n]; if ( !nu ) k++;
else
{
if (nu < )
i += k + ;
else
j += k + ; if (i == j)
j ++;
k = ; }
}
return min (i, j);
}
下面是Hdu 5442 代码,还是要比sa好很多的 (惬意!!!!)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; const int maxn = ;
int Next[maxn]; int Max_Repre (char s[], int n)
{
int i = , j = , k = ;
while (i<n && j<n && k<n)
{
int nu = s[(i+k)%n] - s[(j+k)%n]; if ( !nu ) k++;
else
{
if (nu < )
i += k + ;
else
j += k + ; if (i == j)
j ++;
k = ; }
}
return min (i, j);
} int Get_Next (char s[], int n)
{
int k = -, i = ;
Next[] = -; while (i < n)
{
if (k == - || s[k]==s[i])
Next[++i] = ++k; else
k = Next[k];
} if (n % (n - Next[n]))
return n;
return n - Next[n];
} void display (char a[], char s[], int x, int n)
{
for (int i=; i<n; i++)
a[i] = s[(x+i)%n]; a[n] = ;
} //a大,return true,b大 return false
bool Judge (int a, int b, char A[], char B[])
{
int k = strcmp (A, B); if (k == )
return a<=b ? true:false;
return k>?true:false;
} int main ()
{
int t, n, k, a, b;
char S[maxn], A[maxn], B[maxn];
scanf ("%d", &t); while (t --)
{
scanf ("%d %s", &n, S); k = Get_Next (S, n);
a = Max_Repre (S, n);
display (A, S, a, n); strrev (S);
b = Max_Repre (S, n);
display (B, S, b, n);
b = (n - b - ) % k; if (Judge (a, b, A, B))
printf ("%d 0\n", a + );
else
printf ("%d 1\n", b + );
}
return ;
}
最新文章
- MySQL中索引和优化的用法总结
- .Net深复制、浅复制
- 【吉光片羽】奇怪的Bug-细节的问题
- CSS层模型
- RTTI的实现(vc)--转载
- C# 代码转化为Java代码
- Winform开发框架之权限管理系统改进的经验总结(1)-TreeListLookupEdit控件的使用
- c#中 ==与equals有什么区别【转】
- c标准库和运行时库
- backtracking问题
- 云计算的三种服务模式IaaS、PaaS和SaaS的差别
- 前端MVC Vue2学习总结(四)——条件渲染、列表渲染、事件处理器
- Ubunttu16.04升级/更新git版本(亲测有效)
- BBS论坛(十二)
- PHP filter_var 函数用法
- JVM运行时数据区内容简述
- python查看对象用法
- C#学习笔记(30)——系统自带委托Func和Action
- Boosting 简单介绍
- 【Matlab】让Matlab程序发出声音
热门文章
- CodeVS2492 上帝造题的七分钟2(树状数组+并查集)
- vc++6.0中右键点击";转到定义";为什么是";未定义符号";呢?
- 小程序 swiper banner 图片 居中
- ABAP debug遇到问题
- nodejs 实战
- PrintWrite
- ajax访问json文件缓存问题
- springboot 项目 docker化部署
- Vue中 key keep-alive
- codeforces B. Sereja and Mirroring 解题报告