最小表示法
http://www.fjutacm.com/Problem.jsp?pid=2411
看到这题,我第一反应简单啊,刷刷刷把代码敲好交了一发
#include<stdio.h> #include<string.h> int main() { char s1[200000],s2[200000],s3[200000]; int l,k; while(~scanf("%s",s1)){ k=0; l=strlen(s1); strcpy(s3,s1); strcpy(s2,s1); strcat(s1,s2); while(strcmp(s3,s2)>=0){ k++; for(int i=0;i<l;i++){ s3[i]=s1[i+k]; } } puts(s3); } return 0; }
不就比较字典序嘛,一个strcmp就解决了,很快啊
然后果不其然
然后寻找大佬帮助,大佬的思路如下:
1.双指针i,j;
2.通过"把已经比较过相等的字符跳过,从最后一个相等的字符的下一个字符开始比较字典序。"的方法降低时间复杂度;
3.然后就是i+k和j+k的三种情况,相等小于大于分别处理;
4.注意事项:i+k要取模防止溢出;i+k和j+k不相等时k=0;i和j相等时i++或者j++,要使它们指向两个不同的位置;
5.最后取i和j里小的那一个。
放代码:
#include<stdio.h> #include<string.h> int main() { char s[200005]; int i,j,l,k,x; while(~scanf("%s",s)){ i=0,j=1,k=0; l=strlen(s); while(i<l&&j<l&&k<l){ if(s[(i+k)%l]==s[(j+k)%l]) k++; else if(s[(i+k)%l]<s[(j+k)%l]){ j=j+k+1; if(i==j) j++;//i和j要指向不同位置 k=0;//k要重置为0 } else if(s[(i+k)%l]>s[(j+k)%l]){ i=i+k+1; if(i==j) i++; k=0; } } if(i<j) x=i; else x=j; for(int i=0;i<l;i++){ printf("%c",s[(i+x)%l]); } printf("\n"); } return 0; }
PS:感谢大佬友情提示!
EOF