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)(算出所有子串个数) 然后将母串放入后缀自动机 ...
随机推荐
- .net 自定义AOP,透明代理与真实代理
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.R ...
- easyui-tabs扩展根据自定义属性打开页签
.增加扩展 <script type="text/javascript" > /** * @author {kexb} easyui-tab扩展根据id切换页面 */ ...
- IE6 BUG及解决方案
1.IE6中奇数宽高的BUG 一个外部的相对定位div,内部一个绝对定位的div(right:0) 可是在IE6下查看,却变成了right:1px的效果了: 解决方案就是将外部相对定位的div宽度改成 ...
- Perl 学习笔记-正则表达式基础篇
1.Perl中的正则表达式 在Perl中叫做模式, 是一个匹配(或不匹配)某字符串的模板, 是一种小程序, 对于一个字符串, 要么匹配, 要么不匹配. 使用简易模式: 将模式写在一对正斜线(/)中即可 ...
- HDU 4514 湫湫系列故事――设计风景线 (树形DP)
题意:略. 析:首先先判环,如果有环直接输出,用并查集就好,如果没有环,那么就是一棵树,然后最长的就是树的直径,这个题注意少开内存,容易超内存, 还有用C++交用的少一些,我用G++交的卡在32764 ...
- JAVA中简单的MD5加密类(MD5Utils)
MD5加密分析: JDK API: 获取对象的API: 加密的API: package cn.utils; import java.security.MessageDigest; im ...
- A Multi-Sensorial Simultaneous Localization and Mapping (SLAM) System for Low-Cost Micro Aerial Vehicles in GPS-Denied Environments
A Multi-Sensorial Simultaneous Localization and Mapping (SLAM) System for Low-Cost Micro Aerial Vehi ...
- SQL server 累加求和
1. SELECT SalesOrderID, ProductID, OrderQty ,SUM(OrderQty) OVER(PARTITION BY SalesOrderID) AS Tot ...
- Python 操作 Excel 、txt等文件
#xlrd 读取excel import xlrd import os #获取文件路径 filepath = os.path.join(os.getcwd(),'user_info') #获取文件名称 ...
- cocos2dx conversion to dalvik format failed
标题的这个问题不知道有没有朋友遇到过,我就被害惨了一个晚上加一个早上的时间了. 可能其他朋友很多搜conversion to dalvik format failed 都会看到一样的答案,我是针对做c ...