HDU 5442 后缀自动机(从环字符串选定一个位置 , 时针或顺时针走一遍,希望得到字典序最大)
http://acm.hdu.edu.cn/showproblem.php?pid=5442
题目大意:
给定一个字符串,可理解成环,然后选定一位置,逆时针或顺时针走一遍,希望得到字典序最大,如果同样大,希望找到起始位置最小的,如果还相同,就默认顺时针
后缀自动机上s记录达到的最长的位置,如果不更新,那么必然一次跑完得到的是最小位置,那么为了得到最大,之前更新每一个节点中的s,只有儿子位置上的能更新父亲
所以先将后缀自动机拓扑排序,然后从后往前,不断将父亲的s更新成更大的s
#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 80100
#define ull unsigned long long
char str[N] , tmp[N];
int n , num[N];
queue<int> Q; struct SamNode{
SamNode *son[M] , *f;
int l , s;
void init(){
for(int i= ; i<M ; i++) son[i] = NULL;
f = NULL;
l = s = ;
}
}*b[N]; SamNode sam[N] , *root , *last;
int cnt; void init(){
cnt = ;
sam[].init();
root = last = &sam[];
} void add(int x){
sam[cnt+].init();
SamNode *p = &sam[++cnt] , *jp=last;
/*
这里p->s = jp->s+1写成p->s = p->l也是一样的,因为对于每次当前的last来说,
l和s的值是一样的,因为每次当前的last都是处于字符串的位置上的
数,不是额外添加的节点
*/
p->l = jp->l+; p->s = jp->s+;
last = p;
for(; jp&&!jp->son[x] ; jp=jp->f) jp->son[x] = p;
if(!jp) p->f=root;
else{
if(jp->l+ == jp->son[x]->l) p->f = jp->son[x];
else{
sam[cnt+].init();
SamNode *r = &sam[++cnt] , *q = jp->son[x];
*r=*q;
r->l = jp->l+ ; r->s = p->l;
q->f = p->f = r;
for(; jp && jp->son[x]==q ; jp=jp->f) jp->son[x]=r;
}
}
} int solve(int len)
{
SamNode *cur = root;
for(int i= ; i<len ; i++){
for(int j= ; j>= ; j--){
if(cur->son[j]){
cur = cur->son[j];
break;
}
}
}
int ret = cur->s-len+; return ret;
} int solve1(int len)
{
memset(num , , sizeof(num));
for(int i= ; i<=cnt ; i++) num[sam[i].l]++;
for(int i= ; i<=len* ; i++) num[i] += num[i-];
for(int i= ; i<=cnt ; i++) b[--num[sam[i].l]] = &sam[i];
for(int i=cnt- ; i>= ; i--){
b[i]->f->s = max(b[i]->f->s , b[i]->s);
}
SamNode *cur = root;
for(int i= ; i<len ; i++){
for(int j= ; j>= ; j--){
if(cur->son[j]){
cur = cur->son[j];
break;
}
}
}
int ret = cur->s-len+;
return ret;
} int main() {
// freopen("a.in" , "r" , stdin);
// freopen("out.txt" , "w" , stdout);
int T;
scanf("%d" , &T);
while(T--){
scanf("%d" , &n);
scanf("%s" , str);
int len = n;
init();
for(int i= ; i<len ; i++)
str[len+i] = str[i];
for(int i= ; i<len* ; i++)
add(str[i]-'a');
// for(int i=0 ; i<2*n ; i++) cout<<str[i];
//cout<<endl;
int ret1 = solve(len); for(int i= ; i<len ; i++){
tmp[len-i-] = str[i];
}
for(int i= ; i<len ; i++){
tmp[len+i] = tmp[i];
} init();
for(int i= ; i<len*- ; i++)
add(tmp[i]-'a');
int ret2 = len-solve1(len)+; // cout<<"here: "<<ret1<<" "<<ret2<<endl;
// cout<<ret1<<" "<<ret2<<endl;
int i , j , cnt , pos , wise=-;
for(i=ret1- , j=ret2+len- , cnt= ; cnt<len ; cnt++ , i++ , j--){
// cout<<cnt<<" "<<i<<" "<<j<<" "<<str[i]<<" "<<str[j]<<endl;
if(str[i]>str[j]){wise=;pos=ret1;break;}
else if(str[i]<str[j]){wise=;pos=ret2;break;}
}
if(wise==-){
if(ret1<ret2) pos = ret1 , wise = ;
else if(ret1>ret2) pos = ret2 , wise = ;
else pos=ret1 , wise=;
// cout<<"in: "<<endl;
}
printf("%d %d\n" , pos, wise);
}
return ;
}
HDU 5442 后缀自动机(从环字符串选定一个位置 , 时针或顺时针走一遍,希望得到字典序最大)的更多相关文章
- HDU 5442 后缀自动机+kmp
题目大意: 给定一个字符串,可理解成环,然后选定一位置,逆时针或顺时针走一遍,希望得到字典序最大,如果同样大,希望找到起始位置最小的,如果还相同,就默认顺时针 比赛一直因为处理最小位置出错,一结束就想 ...
- hdu 6208(后缀自动机、或者AC自动机
题意:给你n个字符串,问你是否存在一个字符串可以从中找到其他n-1个字符串. 思路:其实很简单,找到最长的那个字符串对他进行匹配,看是否能匹配到n-1个字符串. 可以用AC自动机或者后缀自动机做,但是 ...
- HDU 4436 (后缀自动机)
HDU 4436 str2int Problem : 给若干个数字串,询问这些串的所有本质不同的子串转换成数字之后的和. Solution : 首先将所有串丢进一个后缀自动机.由于这道题询问的是不同的 ...
- HDU 4622 (后缀自动机)
HDU 4622 Reincarnation Problem : 给一个串S(n <= 2000), 有Q个询问(q <= 10000),每次询问一个区间内本质不同的串的个数. Solut ...
- HDU 4416 (后缀自动机)
HDU 4416 Good Article Good sentence Problem : 给一个串S,和一些串T,询问S中有多少个子串没有在T中出现. Solution :首先对所有的T串建立后缀自 ...
- Boring counting HDU - 3518 后缀自动机
题意: 对于给出的字符串S, 长度不超过1000, 求其中本质不同的子串的数量, 这些子串满足在字符串S中出现了至少不重合的2次 题解: 将串放入后缀自动机中然后求出每一个节点对应的子串为后缀的子串出 ...
- Alice's Classified Message HDU - 5558 后缀自动机求某个后缀出现的最早位置
题意: 给定一个长度不超过 10W 的只包含小写字母的字符串,从下标 0 到 n−1.从下标 0 开始操作, 每次对于下标 pos查找下标 pos 开始的子串中最长的在其他地方出现过的长度,其他出现的 ...
- str2int HDU - 4436 后缀自动机求子串信息
题意: 给出 n 个串,求出这 n 个串所有子串代表的数字的和. 题解; 首先可以把这些串构建后缀自动机(sam.last=1就好了), 因为后缀自动机上从 root走到的任意节点都是一个子串,所有可 ...
- 不在B中的A的子串数量 HDU - 4416 (后缀自动机模板题目)
题目: 给定一个字符串a,又给定一系列b字符串,求字符串a的子串不在b中出现的个数. 题解: 先将所有的查询串放入后缀自动机(每次将sam.last=1)(算出所有子串个数) 然后将母串放入后缀自动机 ...
随机推荐
- query使用
1.row_array():返回查询结果中的第一条数据 include APP_PATH . "../mysql.class.php";$db = new mysql();$sql ...
- [SoapUI] SoapUI+Groovy中"org.apache.xmlbeans.XmlException: error:
把 def holder = groovyUtils.getXmlHolder("Get Token#Response") 改为 def holder = groovyUtils. ...
- es学习-重建索引
url:POST http://127.0.0.1:9200/_reindex 参数: {"source":{"index":"myes"} ...
- js教程系列32 :javascript-DOM节点操作
1 DOM节点操作 1.1 创建节点 createElement() var createDiv = document.createElement("div"); 1.2 插入子节 ...
- 编写高质量代码改善C#程序的157个建议——建议132:考虑用类名作为属性名
建议132:考虑用类名作为属性名 一般来说,若果属性对应一个类型,应该直接用类型名命名属性名.如下: class Person { public Company Company { get; set; ...
- sql 两大类 DDL数据定义语言 和DCL数据控制语言
SQL分为五大类: DDL:数据定义语言 DCL:数据控制语言 DML:数据的操纵语言 DTL:数据事务语言 DQL:数据查询语言. DDL (date definition lang ...
- JavaScript - this详解 (二)
用栗子说this Bug年年有,今年特别多 对于JavaScript这么灵活的语言来说,少了this怎么活! function 函数 this 对于没有实例化的function,我们称之为函数,即没有 ...
- iTerm2 + Oh My Zsh 打造舒适终端体验
iTerm2 + Oh My Zsh 打造舒适终端体验 写在前面 最终效果图: 因为powerline以及homebrew均需要安装command line tool,网络条件优越的同学在执行本文下面 ...
- 解决Hbuilder打包的apk文件按手机返回键直接退出软件
问题描述:Hbuilder打包的app如果点击手机返回键,app会直接退出,返回不了上一页. 写在公共js文件中,每个页面均引入该js,代码如下: document.addEventListener( ...
- [原创] 改善 Firemonkey Canvas 几何绘图质量问题(移动平台)
说明: Fiiremonkey 的跨平台能力,大家有目共睹(一码同介面跨四平台),唯独移动平台在几何绘图方面,质量始终不尽人意,我也曾试着去修正(如:修正曲线平滑问题),也曾找过第三方案(如:AggP ...