NOIPの模拟_2016_7_19_t2_弄提纲

来源:互联网 发布:淘宝企业店铺委托书 编辑:程序博客网 时间:2024/05/18 22:18

题目

Description

新日暮里中,比冲是一位博学的哲学教授。由于最近要帮学生准备考试,他决定弄个提纲给学生。然而同事van不服气,觉得这样学生就没有了自我思考,便在提纲中添加废话。
比冲很无奈,他想找回原稿。我们把现在的提纲看成是一个字符串S。他知道van只会在原稿结尾添加语句,也就是说,原稿是S的前缀。
现在比冲有m个询问,以此来找出原稿。每次给出两个位置l,r,问以l与r结尾的字符串中,有多少个字符串符合原稿的性质,最长的有多长。

Input

第一行一个只包含小写字母的字符串S,代表被改过的提纲。注意字符串从1开始编号。
第二行一个正整数m,即询问数。
接下来m行,每行两个正整数l,r,即位置。

Output

共m行,每行两个正整数a,b,a表示有多少个合法字符串,b为最长合法字符串长度。

Sample Input

输入1:
nguangdongren
2
5 13
6 10
输入2:
ababbaabbaababab
3
14 16
3 6
2 4

Sample Output

输出1:
1 1
1 2
输出2:
2 4
1 1
1 2

Data Constraint

30%:|S|<=300;m<=300
60%: |S|<=3000;m<=100000
100%:|S|<=30000;m<=100000
当我打这一题的题解时已经快要下课啦,为了不影响我的腐败宿舍生活,我决定很无耻的随便随便乱扯两句草草了事23333,我们处理出kmp中的fail数组,设fail[i]为i
的父亲,根节点的深度为零,用这样的方法建立一棵tree,对于每次的查询x,y我们用倍增找到他们的lca,然后输出他们lca的深度以及lca的位置就可以了。
贴代码(我感觉我的倍增打的好丑啊2333)

var    deep,next:array[0..30005]of longint;    f:array[0..30005,0..20]of longint;    bz:array[0..30005]of boolean;    s:ansistring;    i,j,k,l,n,x,y,len,p:longint;procedure dfs(x:longint);begin    if deep[next[x]]=0 then dfs(next[x]);    deep[x]:=deep[next[x]]+1;end;procedure kmp;begin    readln(s);    len:=length(s);    for i:=2 to len do    begin        while (j>0) and (s[j+1]<>s[i]) do j:=next[j];        if s[j+1]=s[i] then inc(j);        next[i]:=j;        bz[j]:=true;        f[i,0]:=j;    end;end;procedure makefather;begin    for j:=1 to p do        for i:=1 to len do            f[i,j]:=f[f[i,j-1],j-1];end;begin    kmp;    deep[0]:=1;    for i:=2 to len do if bz[i]=false then dfs(i);    i:=1;    p:=0;    while i<len do    begin        i:=i*2;        inc(p);    end;    if i>len then dec(p);    makefather;    readln(n);    for i:=1 to n do    begin        readln(x,y);        if deep[x]<deep[y] then        begin            l:=x;            x:=y;            y:=l;        end;        l:=deep[x]-deep[y];        j:=1;        k:=0;        while l>0 do        begin            if l and 1=1 then x:=f[x,k];            inc(k);            j:=j*2;            l:=l div 2;        end;        k:=0;        j:=1;        while j<deep[x] do        begin            j:=j*2;            inc(k);        end;        if j>deep[x] then dec(k);        for j:=k downto 0 do            if f[x,j]<>f[y,j] then            begin                x:=f[x,j];                y:=f[y,j];            end;        if x<>y then x:=f[x,0];        writeln(deep[x]-1,' ',x);    end;end.
1 0
原创粉丝点击