关闭

【NOIP2013模拟】归途与征程 题解+代码

331人阅读 评论(0) 收藏 举报
分类:

Description

这里写图片描述

Input

第一行为字符串A。
第二行为字符串B。

Output

输出在B的所有循环同构串中,有多少个能够与A匹配。

Sample Input

输入1:
aaaa
aaaa
输入2:
a*a
aaaaaa
输入3:
* a*b*c *
abacabadabacaba

Sample Output

输出1:
4
输出2:
6
输出3:
15

Data Constraint

对于30%的数据,M<=20;
对于80%的测试点,M<=200;
对于100%的测试点,1<=N<=100,1<=M<=100000。

Solution

30%随便爆搜
80%发现O(n3)甚至更多一点都能过,那么就准备好有一点水准的暴力
分析题目,可以发现,实质上就是字符串A被分成若干个小字符串,每个小字符串要按顺序分别与字符串B匹配即可。不过,如果前后不是的话就把前后先走到然后再做。之后说的开头或者结尾都是以开头或结尾的。
先把B复制一份,然后可以用两个指针i和j,分别指着A的开头和枚举的B的开头,一个个做,以为分界点。如果当前字符匹配成功,就把i+1,j+1。如果当前字符匹配失败,就把i还原到这一个小字符串的开头,j变成这次匹配之前的位置+1,知道i超过A的长度或j超过应到达的地方就结束。
最后,只有i和j都超过了结尾,才能算一个匹配成功。O(n2)或更大一些。
100%
有一种DP的做法,但是我用的是80分的爆搜加个优化。
B已经被复制。
A串被分割之后,从1开始给每个小字符串标号。用一个预处理F[i,j]表示字符串B从i这个字符之后,第j个小字符串最早从B串的哪个位置开始。那么每次就只用跳到对应的位置就行了,如果已经跳过了n个位置,却还没有把所有小字符串做完,就不可行。单次匹配时间复杂度降为O(m)
怎么预处理F呢?思考一下要做的是什么。在一个字符串里面匹配字符串。很显然,用KMP就行了。KMP模板
另:调试时不要相信PASCAL

Code

var
    n,i,j,k,kk,ans,m,l,q,jy,jy2:longint;
    t,s,s1:ansistring;
    ch:char;
    bz,bz2:boolean;
    next,long:array[1..110] of longint;
    a:array[1..200020,1..110] of longint;
procedure getnext(s:ansistring);
var
    i,j,n:longint;
begin
    n:=length(s);j:=0;
    for i:=2 to n do
    begin
        while (j>0)and(s[i]<>s[j+1]) do j:=next[j];
        if (s[i]=s[j+1]) then inc(j);
        next[i]:=j;
    end;
end;
procedure kmp(s:ansistring;k:longint);
var
    m,i,j:longint;
begin
    j:=0;m:=length(s);
    for i:=2 to 2*n do
    begin
        while (j>0)and(t[i]<>s[j+1]) do j:=next[j];
        if (t[i]=s[j+1]) then inc(j);
        if j=m then begin a[i-long[k]+1,k]:=i-long[k]+1;j:=next[j];end;
    end;
end;
begin
    readln(s);readln(t);
    m:=length(s);n:=length(t);t:=t+t;s:=s+'!';t:=t+'@';i:=1;kk:=0;
    while i<=m do
    begin
        s1:='';while (s[i]='*')and(i<=m) do inc(i);
        while (s[i]<>'*')and(i<=m) do begin s1:=s1+s[i];inc(i);end;
        if (i<=m) then
        begin
            fillchar(next,sizeof(next),0);getnext(s1);
            inc(kk);long[kk]:=length(s1);kmp(s1,kk);
        end;
    end;
    for i:=1 to kk do
    begin
        for j:=2*n downto 1 do
        begin
            if (j=2*n)and(a[j,i]=0) then a[j,i]:=2*n+1;
            if a[j,i]=0 then a[j,i]:=a[j+1,i];
        end;
    end;
    for i:=1 to n do
    begin
        bz:=true;
        j:=1;k:=i;q:=kk;l:=i+n-1;
        if (s[m]<>'*') then
        begin
            while (s[m+l-i-n+1]<>'*')and(l>=k) do
            begin
                if s[m+l-i-n+1]=t[l] then dec(l)
                else begin bz:=false;break;end;
            end;
            dec(q);
        end;
        if (s[1]<>'*') then
        begin
            while (s[k-i+1]<>'*')and(k<=l) do
            begin
                if s[k-i+1]=t[k] then inc(k)
                else begin bz:=false;break;end;
            end;
            inc(j);
        end;
        if bz=false then continue;
        while (j<=q)and(k<=l) do
        begin
            k:=a[k,j]+long[j];inc(j);
        end;
        if (bz)and(j>q)and(k<=l+1) then inc(ans);
    end;
    writeln(ans);
end.
1
0
查看评论

【NOIP2013模拟】归途与征程

Description给出两个字符串,A和B,|A|=n,|B|=m,并且A中有许多*——通配符。这个东西可以匹配任意的字符串,包括空串。现在问你,B的循环同构的字符串中,有多少个可以和A匹配? n<=100,m<=10^5Solution什么东东? 还以为是扩k呢。。。 实际上只...
  • alan_cty
  • alan_cty
  • 2016-05-30 19:46
  • 765

[JZOJ3427]【NOIP2013模拟】归途与征程

DescriptionSolution注意,这里的匹配是全部都要匹配,不能落下一点。Code
  • hzj1054689699
  • hzj1054689699
  • 2016-06-01 12:47
  • 229

[jzoj]3427. 【NOIP2013模拟】归途与征程(字符串DP+贪心)

Problem给定一个A串,一个B串,A串的’* ‘可以匹配B串的任意多个字符,若除’*’以外所有字符一一对应,则称A,B匹配,求在B串所有的循环串中有多少个与A匹配.Data constraint对于30%的数据,M<=20;对于80%的测试点,M<=200;对于100%的测试点,1&...
  • Algor_pro_king_John
  • Algor_pro_king_John
  • 2017-08-18 21:35
  • 171

JZOJ3427. 【NOIP2013模拟】归途与征程 (2017.8B组)

https://jzoj.net/senior/#main/show/3427 想法: 先把A串中所有连成一块的不含“”的子串提取出来,把b串copy一份,求f[i][j]表示b串第i位到i+len位是否和a串的第j个子串匹配(hash或暴力),然后在求一个next[i][j]表示i及后...
  • puppywolf
  • puppywolf
  • 2017-08-17 22:36
  • 85

NOIP2013 货车运输 解题报告(最大生成树+倍增lca)

在线评测: http://codevs.cn/problem/3287/ 整体思路: 我们先看一下题,题中需要使道路上的边的最小值尽可能的大,而且并不关心距离之类的东西,保证尽可能的联通即可,所以我们来最大生成树。然后我们想一下,如在在一棵树上快速的求出两点间的路径的最小值,我们可以利用倍增l...
  • qq_35772697
  • qq_35772697
  • 2016-10-01 11:00
  • 360

noip2013 简要题解

day1  P1 ans = (x + m *(10^k )) %n   10^k %n 用快速幂计算即可 #include using namespace std; long long n,m,k,x; long long power(long long x, lo...
  • KQZXCMH
  • KQZXCMH
  • 2013-12-04 22:40
  • 2917

归途与征程

题目描述简单的思路把B串倍长,那么新的串任意一个长度为M的子串都是B的循环同构串。 按照*号把A串分成了若干段,然后每一段都与B串做一次KMP匹配。 具体的,设一个bz[i,j]表示B串第i个位置为开头是否能与第j段匹配。 那么统计答案就是枚举循环同构串的头部,不断往后跑。 当然,如果A串的...
  • WerKeyTom_FTD
  • WerKeyTom_FTD
  • 2016-05-28 14:57
  • 340

NOIP 2013 提高组题解 【附AC代码】

NOIP2013 提高组题解
  • u012274244
  • u012274244
  • 2013-11-19 15:28
  • 2772

归途与征程 Journey

题目描述:“感谢你们来访 Nescafe 之塔,封印的能量会在两天之内完全被贮存在神杯之中,你们也该回去了。” “不过圣主,我们还有一个问题。难道……Nescafe 就这样被封印成一座神杯,保存在塔中了吗?” “也许吧。谁知道呢?或许来年的秋天会有有识之士来开启它呢……” “有识之士?他是谁?...
  • zhangche0526
  • zhangche0526
  • 2017-02-07 19:56
  • 175

jzoj 3427 归途与征程

jzoj 3427
  • ssl_lyy
  • ssl_lyy
  • 2017-08-18 21:56
  • 116
    个人资料
    • 访问:108156次
    • 积分:4202
    • 等级:
    • 排名:第8663名
    • 原创:296篇
    • 转载:2篇
    • 译文:0篇
    • 评论:41条
    博客专栏
    最新评论