NOIPの模拟_2016_7_19_t2_弄提纲

题目

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码配备了详细的注释和文档,助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在职或创业过程,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更这些源码资源,以适应各平台技术的最发展和市场需。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值