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

Posted songorz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ACM-ICPC 2018 焦作赛区网络预赛 H题 String and Times(SAM)相关的知识,希望对你有一定的参考价值。

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 imes 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
",ans);
    }

    return 0;
}

  

以上是关于ACM-ICPC 2018 焦作赛区网络预赛 H题 String and Times(SAM)的主要内容,如果未能解决你的问题,请参考以下文章

ACM-ICPC 2018 焦作赛区网络预赛 B题 Mathematical Curse

ACM-ICPC 2018 焦作赛区网络预赛 G题 Give Candies

ACM-ICPC 2018 焦作赛区网络预赛 L 题 Poor God Water

ACM-ICPC 2018 焦作赛区网络预赛 K题 Transport Ship

ACM-ICPC 2018 焦作赛区网络预赛J题 Participate in E-sports

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