G2. 唐纳德与子串 (Hard)kmp

来源:互联网 发布:js字符串叠加 编辑:程序博客网 时间:2024/05/22 01:41
G2. 唐纳德与子串 (Hard)

Time limit per test: 2.5 seconds

Memory limit: 512 megabytes

子串的定义是在一个字符串中连续出现的一段字符。这里,我们使用 s[lr] 来表示 s 字符串从 l 到 r(闭区间)的子串。在本题中,字符串下标从 0 开始。显然,对于长度为 n 的字符串共有 n(n+1)2 个子串。

对于一个给定的字符串 s,唐纳德给出 q 次询问,第 i 次询问包括三个参数 li,ri,zi,问在 s[liri] 的所有子串中共有多少个恰好为 zi

Input

输入具有如下形式:

sql1 r1 z1l2 r2 z2lq rq zq

第一行一个字符串 s

第二行一个整数 q

接下来每行:首先两个整数 li,ri (0liri<|s|),然后是一个非空字符串 zi。整数和整数,整数和字符串间以单空格隔开。

字符串中只会出现 26 个小写英文字母。

数据规模约定:

  • 对于 Easy 档:1|s|100,q|zi|100
  • 对于 Hard 档:1|s|105,q|zi|105

Output

对于每次询问,输出一个整数,表示答案。

Examples

input
thisisagarbagecompetitionhahahah50 30 a1 5 is25 30 hah6 12 ag7 12 ag
output
62221
#include <iostream>#include <cstring>using namespace std; int l,r,p,sum;int next[100000];string s,z;void gtnext(){    int k=-1,j=0;    next[0]=-1;    while(j<z.size())    {        if(k==-1||z[j]==z[k])        {            j++;            k++;            if(z[j]!=z[k])                next[j]=k;            else                next[j]=next[k];        }        else            k=next[k];    }}int kmp(){    int j=l,k=0;    while(j<=r)    {        if(k==-1||s[j]==z[k])        {            j++;            k++;        }        else            k=next[k];    if(k==z.size())       {           sum++;           k=next[k];       }    }    cout<<sum<<endl;}int main(){    cin>>s;    cin>>p;    for(int i=0;i<p;++i)    {        sum=0;        cin>>l>>r;        cin>>z;        memset(next,0,sizeof(next));        gtnext();        kmp();    }    return 0;}

原创粉丝点击