[USACO5.5.2]Hidden Password

来源:互联网 发布:java代码大全 下载 编辑:程序博客网 时间:2024/06/05 20:15

给定一个字符串,求其循环得到的len个字符串中,字典序最小的那个串的开头是原串的第几个字符

做法:最小表示法(本来想哈希+乱搞的)

什么是最小表示法呢?顾名思义,就是其串循环后字典序最小的那个串来表示整个串。

先上一段代码——应该比网上的精简多了,去掉了一些感觉没什么用的剪枝——可能我错,但是能过。


int work(int n){int i=0,j=1,k;while (i<n && j<n){for (k=0;k<n && s[(i+k)%n] == s[(j+k)%n];k++);if (s[(i+k)%n] > s[(j+k)%n]) i=i+k+1; else j=j+k+1;if (i == j) i=j+1;}return min(i,j);}
没错,这就是最小表示法微笑

很短吧。

我们来解析一下具体的做法:首先,考虑用2个指针来扫描,分别从0和1开始。

那么扫描什么呢?得到它们之后最长的相同部分。

假设是s[i]~s[i+k-1]和s[j]~s[j+k-1]——当然,这里不写mod了

首先s[i]~s[i+k-1]和s[j]~s[j+k-1]这一段是相同的 假设s[i+1]~s[i+k]中的某一个的是最小表示法的开头 设为s[i+t]那么容易发现,如果s[j+k]<s[i+k],那么说明s[j+t]比s[i+t]更优,所以s[i+t]不可能成为最小表示法的开头 同理,如果s[j+k]>s[i+k],那么s[j]~s[j+k]都不可能是最小表示法的开头跑得很快

Executing...   Test 1: TEST OK [0.000 secs, 4276 KB]   Test 2: TEST OK [0.000 secs, 4276 KB]   Test 3: TEST OK [0.000 secs, 4276 KB]   Test 4: TEST OK [0.000 secs, 4276 KB]   Test 5: TEST OK [0.000 secs, 4276 KB]   Test 6: TEST OK [0.000 secs, 4276 KB]   Test 7: TEST OK [0.000 secs, 4276 KB]   Test 8: TEST OK [0.000 secs, 4276 KB]   Test 9: TEST OK [0.000 secs, 4276 KB]   Test 10: TEST OK [0.000 secs, 4276 KB]   Test 11: TEST OK [0.000 secs, 4276 KB]   Test 12: TEST OK [0.000 secs, 4276 KB]   Test 13: TEST OK [0.000 secs, 4276 KB]   Test 14: TEST OK [0.000 secs, 4276 KB]All tests OK.

据说此题还有后缀数组的做法,而且跑的很慢。

主程序:

scanf("%*d");for (int i=0;~scanf("%s",s+i);i+=72);//读入 printf("%d\n",work(strlen(s)));//处理 

原创粉丝点击