题目链接:http://poj.org/problem?id=1509

题目意思就是求循环字符串的最小表示。

我们用字符串S+S建立SAM,然后从root开始走n步,每次尽量选最小的。

由于 SAM 可以接受 SS 所有的子串,而字典序最小的字符串也必定是 SS 的子串,因此按照上面的规则移动就可以找到一个字典序最小的子串。

这里的right等价类的len显然可以直接扩展到串首,于是开始的位置就是T[o].len-n+1。

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct State{
int ch[],fa,len;
void init(){
fa=-;
len=;
memset(ch,-,sizeof(ch));
}
}T[];
char s[];
int cnt=,la;
void Extend(int c){
int end=++cnt,tmp=la;
T[end].init();
T[end].len=T[tmp].len+;
while(tmp!=-&&T[tmp].ch[c]==-){
T[tmp].ch[c]=end;
tmp=T[tmp].fa;
}
if(!~tmp) T[end].fa=;
else{
int ne=T[tmp].ch[c];
if(T[tmp].len+==T[ne].len) T[end].fa=ne;
else{
int np=++cnt;
T[np].init();
T[np]=T[ne];
T[np].len=T[tmp].len+;
T[end].fa=T[ne].fa=np;
while(tmp!=-&&T[tmp].ch[c]==ne){
T[tmp].ch[c]=np;
tmp=T[tmp].fa;
}
}
}
la=end;
}
int main(){
int Test;
scanf("%d",&Test);
while(Test--){
cnt=;
la=;
T[].init();
scanf("%s",s);
int n=strlen(s);
for(int i=;i<n;i++) Extend(s[i]-'a');
for(int i=;i<n;i++) Extend(s[i]-'a');
int o=;
for(int i=;i<n;i++)
for(int j=;j<;j++)
if(~T[o].ch[j]){
o=T[o].ch[j];
break;
}
printf("%d\n",T[o].len-n+);
}
return ;
}

最新文章

  1. java跳出多重嵌套循环
  2. Document树的解析方法
  3. ABP入门系列(3)——领域层创建实体
  4. operator
  5. JS类库函数收集中....
  6. 用Rational Rose来建立数据库表
  7. Javascript 精髓整理篇之三(数组篇)postby:http://zhutty.cnblogs.com
  8. [小技巧] Python 脚本暴力破解 HC2600 机顶盒管理密码
  9. Android系统APN配置具体解释
  10. Oracle分区表转换
  11. WinFom中经典小游戏(含源码)
  12. C语言——第二次作业(2)
  13. 记一下webstorm快键键
  14. java - day008 -final ,static ,访问控制符.
  15. Vim 常用简单命令
  16. BarTender中如何为称重设备设置秤显示?
  17. C#学习笔记(33)——批量修改word标题
  18. Dockerize PostgreSQL
  19. Shell的18条常用命令整理
  20. struts上传文件报argument type mismatch错误

热门文章

  1. 自己定义验证器——用Struts2框架以框架师的思维灵活做好该事情
  2. OpenCV入门笔记(二) 图片的文件操作
  3. Oracle改动字段类型
  4. 设备没有可用空间 /var/spool/clientmqueue sendmail
  5. Gradle 安装
  6. 【Idea】Debug模式
  7. Git 仓库结构 (二)***
  8. codeforces round#432 div2
  9. (转)Javascript中console.log()用法
  10. P5107 能量采集