HDU 2609 How many
来源:互联网 发布:linux ssh暴力破解 编辑:程序博客网 时间:2024/05/24 02:31
// 找找状态
1.关于最小表示法
循环字符串的最小表示法的问题可以这样描述:
对于一个字符串S,求S的循环的同构字符串S’中字典序最小的一个。
由于语言能力有限,还是用实际例子来解释比较容易:
设S=bcad,且S’是S的循环同构的串。S’可以是bcad或者cadb,adbc,dbca。而且最小表示的S’是adbc。
对于字符串循环同构的最小表示法,其问题实质是求S串的一个位置,从这个位置开始循环输出S,得到的S’字典序最小。
一种朴素的方法是设计i,j两个指针。其中i指向最小表示的位置,j作为比较指针。
令i=0,j=1
如果S[i] > S[j] i=j, j=i+1
如果S[i] < S[j] j++
如果S[i]==S[j] 设指针k,分别从i和j位置向下比较,直到S[i] != S[j]
如果S[i+k] > S[j+k] i=j,j=i+1
否则j++
返回i
起初,我想在j指针后移的过程中加入一个优化。就是j每次不是加1,而是移动到l位置。其中,l>j且S[l]<=S[j]。但是,即使加入这一优化,在遇到bbb…bbbbbba这样的字符串时复杂度将退化到O(n^2)。
注意到,朴素算法的缺陷在于斜体的情况下i指针的移动太少了。针对这一问题改进就得到了最小表示法的算法。最小表示法的算法思路是维护两个指针i,j。
令i=0,j=1
如果S[i] > S[j] i=j, j=i+1
如果S[i] < S[j] j++
如果S[i]==S[j] 设指针k,分别从i和j位置向下比较,直到S[i] != S[j]
如果S[i+k] > S[j+k] i=i+k
否则j++
返回i和j的小者
注意到上面两个算法唯一的区别是粗体的一行。这一行就把复杂度降到O(n)了。
值得一提的是,与KMP类似,最小表示法处理的是一个字符串S的性质,而不是看论文时给人感觉的处理两个字符串。
应用最小表示法判断两个字符串同构,只要将两个串的最小表示求出来,然后从最小表示开始比较。剩下的工作就不用多说了。
2. 题目:
How many
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1882 Accepted Submission(s): 777
How many kinds of necklaces total have.(if two necklaces can equal by rotating ,we say the two necklaces are some).
For example 0110 express a necklace, you can rotate it. 0110 -> 1100 -> 1001 -> 0011->0110.
Each test case include: first one integers n. (2<=n<=10000)
Next n lines follow. Each line has a equal length character string. (string only include '0','1').
4011011001001001141010010110000001
12
代码
#include <iostream>#include <cstdio>#include <cstring>#include <set>using namespace std;int MinimumRepresentation(char *s, int l){ int i = 0, j = 1, k = 0, t; while(i < l && j < l && k < l) { t = s[(i + k) >= l ? i + k - l : i + k] - s[(j + k) >= l ? j + k - l : j + k]; if(!t) k++; else{ if(t > 0) i = i + k + 1; else j = j + k + 1; if(i == j) ++ j; k = 0; } } return (i < j ? i : j);}set<string>fsave;char data[105];char fff[105];int main(){ int n; while(scanf("%d",&n)!=EOF) { fsave.clear(); int i,j; int ans=0; for(i=1;i<=n;i++) { scanf("%s",data); int len =strlen(data); int minnum=MinimumRepresentation(data,strlen(data)); int x=0; memset(fff,0,sizeof(fff)); for(j=minnum;j<len;j++) fff[x++]=data[j]; for(j=0;j<minnum;j++) fff[x++]=data[j]; fsave.insert(fff); } printf("%d\n",fsave.size()); } return 0;}
最近烦心的事情比较多 ,是时候静下来整理一下了;
- hdu 2609 How Many
- hdu 2609 How many
- hdu 2609 How many
- HDU 2609 How Many
- HDU 2609 How many
- hdu 2609 how many
- HDU 2609 How many
- HDU 2609How many
- hdu 2609 How many
- hdu 2609 How many(最小表示法)
- [最小表示法] hdu 2609 How many
- HDU——2609 How many
- [最小表示法] HDU 2609 How many
- HDU - 2609 How many(最小表示法)
- HDU 2609 How many(最小表示法)
- HDU-2609 How many (最小表示法)
- HDU 2609 How many [最小表示法]
- hdu How Many Tables
- 自定义模板引擎_2
- RecyclerView使用详解(三)
- 互联网的安全
- Android 学习笔记(一)
- 20160322 HDU5317 RGCDQ(筛数+树状数组)
- HDU 2609 How many
- ThinkPHP 验证码类 Verify
- 数据结构顺序表
- UE4官方视频学习日志:3rd Person Game with Blueprints
- maven jetty 插件的使用
- git 常见问题解决命令
- C# 理解Thread.Sleep()
- tomcat组成及工作原理
- golang日志中心取日志代码分享