HDU 4691(多校第九场1006) 后缀数组
。。。还能多说什么。
眼角一滴翔滑过。
一直以为题意是当前串与所有之前输入的串的LCP。。。然后就T了一整场。
扫了一眼标程突然发现他只比较输入的串和上一个串?
我心中突然有千万匹草泥马踏过。
然后随手就A了。。。
先RMQ预处理一下,复杂度为nlogn ,然后每次LCP询问只需O(1)的复杂度。
- #include <set>
- #include <map>
- #include <stack>
- #include <cmath>
- #include <queue>
- #include <cstdio>
- #include <string>
- #include <vector>
- #include <iomanip>
- #include <cstring>
- #include <iostream>
- #include <algorithm>
- #define Max 2505
- #define FI first
- #define SE second
- #define ll __int64
- #define PI acos(-1.0)
- #define inf 0x3fffffff
- #define LL(x) ( x << 1 )
- #define bug puts("here")
- #define PII pair<int,int>
- #define RR(x) ( x << 1 | 1 )
- #define mp(a,b) make_pair(a,b)
- #define mem(a,b) memset(a,b,sizeof(a))
- #define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i )
- using namespace std;
- inline void RD(int &ret) {
- char c;
- int flag = 1 ;
- do {
- c = getchar();
- if(c == '-')flag = -1 ;
- } while(c < '0' || c > '9') ;
- ret = c - '0';
- while((c=getchar()) >= '0' && c <= '9')
- ret = ret * 10 + ( c - '0' );
- ret *= flag ;
- }
- inline void OT(int a) {
- if(a >= 10)OT(a / 10) ;
- putchar(a % 10 + '0') ;
- }
- #define N 1000005
- /****后缀数组模版****/
- #define F(x)((x)/3+((x)%3==1?0:tb)) //F(x)求出原字符串的suffix(x)在新的字符串中的起始位置
- #define G(x)((x)<tb?(x)*3+1:((x)-tb)*3+2) //G(x)是计算新字符串的suffix(x)在原字符串中的位置,和F(x)为互逆运算
- int wa[N],wb[N],wv[N],WS[N];
- int sa[N*3] ;
- int rank1[N],height[N];
- int r[N*3];
- int c0(int *r,int a,int b) {
- return r[a] == r[b] && r[a + 1] == r[b + 1] && r[a + 2] == r[b + 2];
- }
- int c12(int k,int *r,int a,int b) {
- if(k == 2)
- return r[a] < r[b] || ( r[a] == r[b] && c12(1 , r , a + 1 , b + 1) );
- else
- return r[a] < r[b] || ( r[a] == r[b] && wv[a + 1] < wv[b + 1] );
- }
- void sort(int *r,int *a,int *b,int n,int m) {
- int i;
- for(i = 0; i < n; i ++)
- wv[i] = r[a[i]];
- for(i = 0; i < m; i++)
- WS[i] = 0;
- for(i = 0; i < n; i++)
- WS[wv[i]] ++;
- for(i = 1; i < m; i++)
- WS[i] += WS[i-1];
- for(i=n-1; i>=0; i--)
- b[-- WS[wv[i]]] = a[i];
- return;
- }
- //注意点:为了方便下面的递归处理,r数组和sa数组的大小都要是3*n
- void dc3(int *r,int *sa,int n,int m) { //rn数组保存的是递归处理的新字符串,san数组是新字符串的sa
- int i , j , *rn = r + n , *san = sa + n , ta = 0 ,tb = (n + 1) / 3 , tbc = 0 , p;
- r[n] = r[n+1] = 0;
- for(i = 0; i < n; i++) {
- if(i % 3 != 0)
- wa[tbc ++]=i; //tbc表示起始位置模3为1或2的后缀个数
- }
- sort(r + 2,wa,wb,tbc,m);
- sort(r + 1,wb,wa,tbc,m);
- sort(r,wa,wb,tbc,m);
- for(p = 1,rn[F(wb[0])] = 0,i = 1; i < tbc; i++)
- rn[F(wb[i])]=c0(r,wb[i - 1],wb[i])?p - 1 : p ++;
- if(p < tbc)
- dc3(rn,san,tbc,p);
- else {
- for(i = 0; i < tbc; i++)
- san[rn[i]]=i;
- }
- //对所有起始位置模3等于0的后缀排序
- for(i = 0; i < tbc; i++) {
- if(san[i] < tb)
- wb[ta ++] = san[i] * 3;
- }
- if(n % 3 == 1) //n%3==1,要特殊处理suffix(n-1)
- wb[ta ++] = n - 1;
- sort(r,wb,wa,ta,m);
- for(i = 0; i < tbc; i++)
- wv[wb[i] = G(san[i])] = i;
- //合并所有后缀的排序结果,保存在sa数组中
- for(i = 0,j = 0,p = 0; i < ta && j < tbc; p ++)
- sa[p] = c12(wb[j] % 3,r,wa[i],wb[j]) ? wa[i ++] : wb[j ++];
- for(; i < ta; p++)
- sa[p] = wa[i++];
- for(; j < tbc; p++)
- sa[p] = wb[j++];
- return;
- }
- //height[i]=suffix(sa[i-1])和suffix(sa[i])的最长公共前缀,也就是排名相邻的两个后缀的最长公共前缀
- void calheight(int *r,int *sa,int n) {
- int i , j , k = 0;
- for(i = 1; i <= n; i++)
- rank1[sa[i]] = i;
- for(i = 0; i < n; height[rank1[i++]] = k)
- for(k ? k -- : 0 , j = sa[rank1[i]-1]; r[i + k] == r[j + k]; k++);
- }
- int RMQ[N];
- int mm[N];
- int best[20][N];
- void initRMQ(int n) {
- int i,j,a,b;
- for(mm[0] = -1,i = 1; i <= n; i++)
- mm[i] = ((i & (i - 1)) == 0)?mm[i - 1] + 1 : mm[i - 1];
- for(i = 1; i <= n; i++) best[0][i] = i;
- for(i = 1; i <= mm[n]; i++)
- for(j = 1; j <= n + 1 - (1 << i); j++) {
- a = best[i - 1][j];
- b = best[i - 1][j + (1 << (i - 1))];
- if(RMQ[a] < RMQ[b]) best[i][j] = a;
- else best[i][j] = b;
- }
- return;
- }
- int askRMQ(int a,int b) {
- int t;
- t = mm[b - a + 1];
- b -= (1 << t ) - 1;
- a = best[t][a];
- b = best[t][b];
- return RMQ[a] < RMQ[b] ? a : b;
- }
- int lcp(int a,int b) {
- int t;
- a = rank1[a];
- b = rank1[b];
- if(a > b) {
- t = a;
- a = b;
- b = t;
- }
- return(height[askRMQ(a + 1,b)]);
- }
- /*********************************************/
- #define N 1000005
- char a[N] ;
- int n ;
- int cal(int now){
- if(now == 0)return 1 ;
- int nn = 0 ;
- while(now){
- nn ++ ;
- now /= 10 ;
- }
- return nn ;
- }
- int main() {
- int ttt = 0 ;
- while(scanf("%s",a) != EOF ) {
- int l = strlen(a) ;
- for (int i = 0 ; i < l ; i ++ )r[i] = a[i] ;
- r[l] = 0 ;
- dc3(r , sa ,l + 1 , 200) ;
- calheight(r , sa , l) ;
- for (int i = 1 ; i <= l ; i ++ )RMQ[i] = height[i] ;
- initRMQ(l) ;
- RD(n) ;
- ll num1 = 0 ,num2 = 0 ;
- int x , y ;
- int prex = -1 , prey = -1 ;
- while(n -- ) {
- RD(x) ;
- RD(y) ;
- num1 += (y - x) + 1 ;
- if(prex == -1){
- num2 += (y - x) + 3 ;
- prex = x ;
- prey = y ;
- continue ;
- }
- int now = 0 ;
- if(x == prex){
- now = min(prey - prex , y - x) ;
- }
- else{
- now = lcp(prex , x) ;
- now = min(prey - prex , min(y - x , now) ) ;
- }
- prex = x ;
- prey = y ;
- int fk = now ;
- now = y - x - now ;
- if(now == 0){
- num2 += 2 + cal(fk) ;
- }else
- num2 += cal(fk) + now + 2 ;
- }
- printf("%I64d %I64d\n",num1 ,num2) ;
- ttt ++ ;
- }
- return 0 ;
- }
HDU 4691(多校第九场1006) 后缀数组的更多相关文章
- hdu 4691 最长的共同前缀 后缀数组 +lcp+rmq
http://acm.hdu.edu.cn/showproblem.php? pid=4691 去年夏天,更多的学校的种族称号.当时,没有后缀数组 今天将是,事实上,自己的后缀阵列组合rmq或到,但是 ...
- hdu多校第九场 1006 (hdu6685) Rikka with Coin 暴力
题意: 有一些1毛,2毛,5毛,1块的钢镚,还有一些价格不同的商品,现在要求你带一些钢镚,以保证这些商品中任选一件都能正好用这些钢镚付账,问最少带多少钢镚. 题解: 对于最优解,1毛的钢镚最多带1个, ...
- 2018 Multi-University Training Contest 9 杭电多校第九场 (有坑待补)
咕咕咕了太久 多校博客直接从第三场跳到了第九场orz 见谅见谅(会补的!) 明明最后看下来是dp场 但是硬生生被我们做成了组合数专场…… 听说jls把我们用组合数做的题都用dp来了遍 这里只放了用组 ...
- 2016暑假多校联合---Substring(后缀数组)
2016暑假多校联合---Substring Problem Description ?? is practicing his program skill, and now he is given a ...
- HDU 5442 Favorite Donut(暴力 or 后缀数组 or 最大表示法)
http://acm.hdu.edu.cn/showproblem.php?pid=5442 题意:给出一串字符串,它是循环的,现在要选定一个起点,使得该字符串字典序最大(顺时针和逆时针均可),如果有 ...
- 【HDU 5030】Rabbit's String (二分+后缀数组)
Rabbit's String Problem Description Long long ago, there lived a lot of rabbits in the forest. One d ...
- HDU 6138 Fleet of the Eternal Throne 后缀数组 + 二分
Fleet of the Eternal Throne Problem Description > The Eternal Fleet was built many centuries ago ...
- hdu多校第一场 1006 (hdu6583)Typewriter dp/后缀自动机
题意: 有个打字机,在当前字符串后新加一个字花费p,把当前字符串的一个连续子串拷贝到当前字符串的末尾花费q,给定一个字符串,求用打字机打出这个字符串的最小花费. 题解: 容易想到用dp 记dp[i]为 ...
- 218多校第九场 HDU 6424 (数学)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6424 题意:定义f(A) = log log log log …. (A个log) n ,g[A,B, ...
随机推荐
- 根据Email地址跳转到相应的邮箱登录页面 (转)
//跳转到指定的邮箱登录页面 $(".btn_actemail").click(function () { var uurl = $(".hide_email" ...
- search_word
一个小程序,用asc码输出自己的名字.要求是,a~z两路输入,输出了一个完整的拼音之后还需要输出一个空格.—— 信息硬件过滤的雏形. module search_word ( clock , rese ...
- php下载远程图片方法总结(curl手动解析header)curl跳转问题解决
常用方法一般有:. file_get_contents file_put_contents readfile($file) //效率很高. 一般代码: /** * 抓取远程图片 * * @param ...
- SpringMVC入门二: 1规范结构, 2简单整合MyBatis
昨天拿springMVC写的helloworld结构不好, 这次先调整一下体系结构 , 然后简单整合一下MyBatis spring的配置还是以注解为主, 不过MyBatis的映射文件什么的还是拿xm ...
- shu_1548 悟空问题(大哥,主妖怪抓走的朋友!)
http://202.121.199.212/JudgeOnline/problem.php?cid=1078&pid=17 分析: 直接暴力了.. . 代码: #include <s ...
- block 解析 - block变量
block变量 上一篇 讲的是block静态变量的特性,这里我们来看一下_block变量.引用官方: You can specify that an imported variable be muta ...
- stm32内部的CAN总线
功能概述: bxCAN是基本扩展CAN(Basic Extended CAN)的缩写,它支持CAN协议2.0A和2.0B:它的设计目标是以最小的CPU负载来高效处理大量的报文.它也支持报文发送的优先级 ...
- 无法启动outlook mapi
office2013 管理员权限,在命令行中定位到office15文件夹,然后运行命令"outlook /importprf ..prf"
- IOS SWIFT 简单操作文件
//Home目录 let homeDirectory = NSHomeDirectory() //Documents目录 苹果建议将程序中建立的或在程序中浏览到的文件数据保存在该目录下,iTunes备 ...
- day8 - isinstance--issubclass-异常处理-自定义异常
一.isinstance(obj, cls) 检查是否obj是否是类 cls 的对象 __author__ = 'Administrator' class Foo(object): pass obj ...