码迷,mamicode.com
首页 > 其他好文 > 详细

ACM-ICPC 2018 焦作赛区网络预赛 H题 String and Times(SAM)

时间:2018-09-15 20:09:10      阅读:251      评论:0      收藏:0      [点我收藏+]

标签:cal   call   输出   line   oar   alc   成功   inpu   case   

Now you have a string consists of uppercase letters, two integers AA and BB. We call a substring wonderful substring when the times it appears in that string is between AA and BB (A \le times \le BAtimesB). Can you calculate the number of wonderful substrings in that string?

Input

Input has multiple test cases.

For each line, there is a string SS, two integers AA and BB.

\sum length(S) \le 2 \times 10^6length(S)2×106,

1 \le A \le B \le length(S)1ABlength(S)

Output

For each test case, print the number of the wonderful substrings in a line.

样例输入

AAA 2 3
ABAB 2 2

样例输出

2
3

题目来源

ACM-ICPC 2018 焦作赛区网络预赛

题解:SAM模板题

参考代码:

//H  求子串出现次数在k1=<num<=k2;
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 4e5+10;
char ss[200005];
const int LetterSize = 26;

int tot, last,ch[MAXN][LetterSize],fa[MAXN],len[MAXN];
int sum[MAXN],tp[MAXN],cnt[MAXN]; 

void init()
{
    last = tot = 1;
    len[1] = 0;
    memset(ch,0,sizeof ch);
    memset(fa,0,sizeof fa);
    memset(cnt,0,sizeof cnt);
}

void add( int x)
{
    int p = last, np = last = ++tot;
    len[np] = len[p] + 1, cnt[last] = 1;
    while( p && !ch[p][x]) ch[p][x] = np, p = fa[p];
    if(p == 0) fa[np] = 1;
    else
    {
        int q = ch[p][x];
        if( len[q] == len[p] + 1)
            fa[np] = q;
        else
        {
            int nq = ++tot;
            memcpy( ch[nq], ch[q], sizeof ch[q]);
            len[nq] = len[p] + 1, fa[nq] = fa[q], fa[q] = fa[np] = nq;
            while( p && ch[p][x] == q)  ch[p][x] = nq, p = fa[p];
        }
    }
}

void toposort()
{
    for(int i = 1; i <= len[last]; i++)   sum[i] = 0;
    for(int i = 1; i <= tot; i++)   sum[len[i]]++;
    for(int i = 1; i <= len[last]; i++)   sum[i] += sum[i-1];
    for(int i = 1; i <= tot; i++)   tp[sum[len[i]]--] = i;
}


int main()
{

    int k1,k2;
	while(scanf("%s",ss)!=EOF)
    {
    	init();
    	scanf("%d%d",&k1,&k2);
	    long long ans=0;
        for(int i=0,len=strlen(ss);i<len;i++) add(ss[i]-‘A‘);
        toposort();
        for(int i=tot;i;i--)
        {
            int p=tp[i],fp=fa[p];
            cnt[fp]+=cnt[p];
            if(cnt[p]>=k1 && cnt[p]<=k2) ans+=len[p]-len[fp];
        }
        printf("%lld\n",ans);
    }

    return 0;
}

  

ACM-ICPC 2018 焦作赛区网络预赛 H题 String and Times(SAM)

标签:cal   call   输出   line   oar   alc   成功   inpu   case   

原文地址:https://www.cnblogs.com/songorz/p/9651909.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!