POJ 1509 循环同构的最小表示法
2015-06-11 12:42
411 查看
题目大意:
给定一个字符串,可以把一段尾部接到头部,这样找到一个最小的字符串
方案一:
利用循环同构中找最小表示的方法来解决
论文参考http://wenku.baidu.com/view/438cad13a2161479171128b6.html
后缀自动机写法:
给定一个字符串,可以把一段尾部接到头部,这样找到一个最小的字符串
方案一:
利用循环同构中找最小表示的方法来解决
论文参考http://wenku.baidu.com/view/438cad13a2161479171128b6.html
#include <cstdio> #include <cstring> #include <iostream> using namespace std; #define N 10005 char s ; inline int minpos(char *s) { int l = strlen(s); int i=0 , j=1 , k=0; while(i<l&&j<l&&k<l){ //这里k<l是防止出现所有数都一样导致无限循环 if(i == j) j++; else if(s[(i+k)%l]>s[(j+k)%l]){ i = i+k+1; k=0; } else if(s[(i+k)%l]<s[(j+k)%l]){ j = j+k+1; k=0; } else k++; } return min(i , j)+1; } int main() { // freopen("a.in" , "r" , stdin); int T; scanf("%d" , &T); while(T--) { scanf("%s" , s); printf("%d\n" , minpos(s)); } return 0; }
后缀自动机写法:
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace std; /* run this program using the console pauser or add your own getch, system("pause") or input loop */ #define M 26 #define N 40100 char str ; struct SamNode{ SamNode *son[M] , *f; int l , s; }; struct Sam{ SamNode sam , *root , *last; int cnt; void init(){ cnt = 0; memset(sam , 0 , sizeof(sam)); root = last = &sam[0]; } void add(int x){ SamNode *p = &sam[++cnt] , *jp=last; /* 这里p->s = jp->s+1写成p->s = p->l也是一样的,因为对于每次当前的last来说, l和s的值是一样的,因为每次当前的last都是处于字符串的位置上的 数,不是额外添加的节点 */ p->l = jp->l+1; p->s = jp->s+1; last = p; for(; jp&&!jp->son[x] ; jp=jp->f) jp->son[x] = p; if(!jp) p->f=root; else{ if(jp->l+1 == jp->son[x]->l) p->f = jp->son[x]; else{ SamNode *r = &sam[++cnt] , *q = jp->son[x]; *r=*q; r->l = jp->l+1 ; r->s = p->l; q->f = p->f = r; for(; jp && jp->son[x]==q ; jp=jp->f) jp->son[x]=r; } } } }sam; int solve(int len) { SamNode *cur = sam.root; for(int i=0 ; i<len ; i++){ for(int j=0 ; j<26 ; j++){ if(cur->son[j]){ cur = cur->son[j]; break; } } } return cur->s-len+1; } int main(int argc, char *argv[]) { // freopen("in.txt" , "r" , stdin); // freopen("out.txt" , "w" , stdout); int T; scanf("%d" , &T); while(T--){ scanf("%s" , str); int len = strlen(str); sam.init(); for(int i=0 ; i<len ; i++) str[len+i] = str[i]; for(int i=0 ; i<len*2 ; i++) sam.add(str[i]-'a'); int ret = solve(len); printf("%d\n" , ret); } return 0; }
相关文章推荐
- Shiro(一) Shiro架构介绍
- Oracle插入或修改 报ORA-01704: 文字字符串太长
- 你走了 --2004-08-27 博客搬家
- http-only的作用
- SAT数学:常用公式之几何
- 找出排序数组中和为给定值的两个数字
- 系统吞吐量(TPS)、用户并发量、性能测试概念和公式
- GMAT语法复习需要掌握的基础能力有哪些
- linux 段错误调试方法
- 来往网页版扫码自动登录的实现原理
- 命名空间“System.Web”中不存在类型或命名空间名称“Optimization”解决方法
- Jquery Ajax调用aspx页面方法
- mysql数据库密码修改总结 --2004-09-02 博客搬家
- oracle学习之路(二)------数组类型/记录类型的使用
- 第三次Sprint
- 30个实用的Linux find命令示例
- 【leetcode】【66】Plus One
- C#绘制椭圆的方法
- Windows + Apache 2.2+Tomcat7 集群配置
- 【算法】6 比较排序之外学习新的线性时间排序