poj 1509
求一个字符串在旋转置换群下最小字典表示。
用的是后缀数组(后缀自动机还是再听听jason_yu讲讲吧,关于right集合的部分还有问题)
最小表示法的思想很有好(判断两个对象在某一置换群划分下,是否等价,可以求出两个对象在该置换群划分下的最小表示,然后比较最小表示)
#include <cstdio>
#include <cstring>
#define min(a,b) ((a)<(b)?(a):(b))
#define N 20010 int n, aa[N];
int sa[N], rk[N], ht[N], vv[N]; void expand( int *s, int *r, int *sa, int *rk, int k ) {
for( int i=; i<=n; i++ )
vv[r[s[i]]]=i;
for( int i=n; i>=; i-- )
if( s[i]>k ) sa[vv[r[s[i]-k]]--] = s[i]-k;
for( int i=n-k+; i<=n; i++ )
sa[vv[r[i]]--] = i;
for( int i=; i<=n; i++ )
rk[sa[i]] = rk[sa[i-]]+(r[sa[i]]!=r[sa[i-]]||r[sa[i]+k]!=r[sa[i-]+k]);
}
void calcht() {
for( int i=,k=; i<=n; i++ ) {
if( rk[i]== ) {
k = ht[i] = ;
continue;
}
int j=sa[rk[i]-];
while( aa[i+k]==aa[j+k] ) k++;
ht[i] = k;
if( k> ) k--;
}
}
void suffix() {
static int tsa[N], trk[N];
for( int i=; i<=; i++ ) vv[i] = ;
for( int i=; i<=n; i++ ) vv[aa[i]]++;
for( int i=; i<=; i++ ) vv[i]+=vv[i-];
for( int i=n; i>=; i-- ) sa[vv[aa[i]]--]=i;
for( int i=; i<=n; i++ )
rk[sa[i]] = rk[sa[i-]]+(aa[sa[i]]!=aa[sa[i-]]);
for( int k=; k<n; k<<= ) {
expand( sa, rk, tsa, trk, k );
for( int i=; i<=n; i++ )
sa[i]=tsa[i], rk[i]=trk[i];
}
calcht();
}
int sov() {
int nn = (n+)>>;
for( int i=; i<=n; i++ )
if( n-sa[i]+>=nn ) {
int rt = sa[i];
for( int j=i+; j<=n && ht[sa[j]]>=nn; j++ )
rt = min( rt, sa[j] );
return rt;
}
return -;
}
int main() {
int T;
scanf( "%d", &T );
while( T-- ) {
static char buf[N];
scanf( "%s", buf+ );
n = strlen( buf+ );
for( int i=; i<=n; i++ )
aa[i+n] = aa[i] = buf[i]-'a'+;
n += n;
suffix();
printf( "%d\n", sov() );
}
}
poj 1509的更多相关文章
- POJ 1509 最小表示法
题目链接:http://poj.org/problem?id=1509 题意:给定一个字符串,求一个起点使字符串从该起点起的字符串字典序最小[题目的字符串起点从1开始] 思路:最小表示法模板题 #de ...
- ●POJ 1509 Glass Beads
题链: http://poj.org/problem?id=1509 题解: 给出一个字符串,有一个操作:把首字符放到末尾,形成新的串.求任意次操作后,字典序最小的串的首字母在原串中的位置.(这就是最 ...
- POJ 1509 Glass Beads 后缀自动机 模板 字符串的最小表示
http://poj.org/problem?id=1509 后缀自动机其实就是一个压缩储存空间时间(对节点重复利用)的储存所有一个字符串所有子串的trie树,如果想不起来长什么样子可以百度一下找个图 ...
- POJ 1509 Glass Beads【字符串最小表示法】
题目链接: http://poj.org/problem?id=1509 题意: 求循环字符串的最小表示. 分析: 浅析"最小表示法"思想在字符串循环同构问题中的应用 判断两字符串 ...
- POJ 1509 Glass Beads
Description 求字符串的最小循环表示. Sol SAM. 把原串复制一遍,建出SAM,然后每次选最小的一个跑 \(len\) 次,这就是最小循环表示的最后一个节点,然后 \(x-len+1\ ...
- UVA 719 / POJ 1509 Glass Beads (最小表示法/后缀自动机)
题目大意: 给出一个长度为N的字符串,求其字典序最小的循环同构. N<=10W. 算法讨论: 算法一.最小表示法.定义题. 算法二.后缀自动机. Codes: #include <iost ...
- POJ 1509 Glass Beads---最小表示法
题意: T组数据,每组数据给出一个字符串,求这个字符串的最小表示发(只要求输出起始位置坐标) SAM入门题(检测板子是否正确). 将字符串S加倍丢进SAM中,然后走字符串长度次,每次贪心的沿最小的边走 ...
- POJ 1509 循环同构的最小表示法
题目大意: 给定一个字符串,可以把一段尾部接到头部,这样找到一个最小的字符串 方案一: 利用循环同构中找最小表示的方法来解决 论文参考http://wenku.baidu.com/view/438ca ...
- CSU训练分类
√√第一部分 基础算法(#10023 除外) 第 1 章 贪心算法 √√#10000 「一本通 1.1 例 1」活动安排 √√#10001 「一本通 1.1 例 2」种树 √√#10002 「一本通 ...
随机推荐
- 安裝HA服務
**************************************************************************************************** ...
- LINUX vim 修改文件 退出
vim 保存退出, 先按ESC ,然后:wq(保存退出)W:write,写入 Q:quit,退出, 也可以直接输入X,代表WQ,也是保存退出 或者 先按ESC,再按shift+ZZ 也是保存退出 正常 ...
- 使用离线包部署kubernetes 1.9.0、kubernetes-dashboard 1.8
=============================================== 2018/3/22_第2次修改 ccb_warlock 更新 ...
- 【前端vue开发架构】vue开发单页项目架构总结
为营销活动设计的前端架构 主要的技术栈为 Vuejs,Webpack,请自行阅读如下技术或者框架的文档: 一.基础说明: node (https://nodejs.org/en/) npm (http ...
- python网络编程-线程队列queue
一:线程queu作用 Python中,queue是线程间最常用的交换数据的形式. 队列两个作用:一个是解耦,一个是提高效率 二:语法 1)队列的类 class queue.Queue(maxsize= ...
- Tomcat 上传war包后 会自动部署
- set IDENTITY_INSERT on 和 off 的设置
qlserver 批量插入记录时,对有标识列的字段要设置 set IDENTITY_INSERT 表名 on,然后再执行插入记录操作;插入完毕后恢复为 off 设置 格式: set IDENTITY ...
- vue组件中的轮播实现
一.直接上代码 <template> <el-row class="Slide"> <el-row class="title"&g ...
- MySQL学习笔记:like和regexp的区别
一.like关键字 like有两个模式:_和% _:表示单个字符,用来查询定长的数据 select name from table where name like '陈__'; %:表示0个或多个任意 ...
- 20155225 2016-2017-2 《Java程序设计》第六周学习总结
20155225 2016-2017-2 <Java程序设计>第六周学习总结 教材学习内容总结 java的输入输出系统 在重新指定标准输入输出时不同: 重新指定标准输入为文档输入时,是这样 ...