【模板】字符串算法-字符串最小表示法
2015-12-04 08:14
323 查看
2014年10月,刚进hdu参加新生赛的时候,就遇到了字符串最小表示法的裸题,然而那时什么都不会的我只得写暴力,自然TLE了。之后在湖南师范大学第六届大学生计算机程序设计竞赛2B上,又做到了同样的裸题。
ps:这套题虽然质量不高,还有两道错题2333,但是有三道裸题(2B字符串最小表示法、3C网络流和6F矩阵快速幂),对这些算法生疏的ACMer,可以拿来练手哦~~
/* 字符串算法-字符串最小表示法模板 这是一个可以用O(n)时间解决"字符串呈环状,每一位置都可以作为首位,找出以哪个位置为开头,可以使得这个字符串的字典序最小(或最大)"问题的算法。 */ #include<stdio.h> #include<string.h> const int M=5e6+10; int casenum,casei; int p; char a[M]; int getmin(char s[]) { int i=0,j=1,k=0;//i和j是两个进行比较的起始匹配位点,k是匹配长度 int len=strlen(s); while(i<len&&j<len&&k<len) { int t=s[(i+k)%len]-s[(j+k)%len];//比较两个串的大小关系 if(t==0)k++;//如果相同,匹配长度增大,比较位置向移 else //如果不同,则字典序大的位置肯定不会是答案,改变那个匹配位点 { if(t>0)i+=k+1; else j+=k+1; if(i==j)j++;//i和j一定要错开 k=0;//匹配长度要重置为0 } } return i<j?i:j;//因为字典序大的位置被后移了,所以较小的位置就是答案 } int main() { scanf("%d",&casenum); while(casenum--) { scanf("%s",a); p=getmin(a); printf("%d\n",p); } } /* 【题意】 字符串呈环状,每一位置都可以作为首位,以哪个位置为开头,可以使得这个字符串的字典序最小(或最大)? 【类型】 字符串算法-字符串最小表示法 【分析】 这个算法其实自己想也能想出来。 因为就算是自己设计的话,也应当是—— 把这个字符串的0号位点与1号位点相比较, 如果一样,继续向后延伸比较, 如果不一样,肯定大的那个显然不会是答案,改变匹配串。 这里其实唯一需要理解的地方就是—— if(t>0)i+=k+1; else j+=k+1; 为什么这里是变成k+1,中间的内容可以完全跳过呢?(比如t>0) 因为我们已经有{s[i]~s[i+k-1]==s[j]~s[j+k-1]了,且有s[i+k]>s[j+k],自然我们选i~i+k中的任意一点都是比j~j+k的相应位置要差的,所以自然可以都略过} 【时间复杂度&&优化】 i,j,k在某个位点都最多从0走到len,所以时间复杂度为O(n) 【trick】 【数据】 Sample Input 4 bcda aaa a adab Sample Output 3 0 0 2 */
ps:这套题虽然质量不高,还有两道错题2333,但是有三道裸题(2B字符串最小表示法、3C网络流和6F矩阵快速幂),对这些算法生疏的ACMer,可以拿来练手哦~~
相关文章推荐
- python --for循环
- (第十二周项目1)图基本算法库
- DVWA系列之4 利用SQLMap进行medium级别注入
- DVWA系列之4 利用SQLMap进行medium级别注入
- test
- python --if语句
- Linux下vsftpd的简单应用(一)
- cocos2d-js开发总结
- 验证分块查找算法
- 博客开张 自嗨自勉
- nagios 自定义插件demo
- [LeetCode]Two Sum II - Input array is sorted
- An universal algorithm design of fixed length substring locating
- An universal algorithm design of fixed length substring locating
- 第14周 项目2 - 二叉树排序树中查找的路径
- 堆和栈的区别
- <meta>标签中的name与http-equiv
- bzoj2337: [HNOI2011]XOR和路径
- 【C++学习与应用总结】2: 关于类型前置声明
- 在MFC中修改opencv的namedWindow窗口位置