Codeforces Contest 1129 problem C Morse Code ——字典树+dp

In Morse code, an letter of English alphabet is represented as a string of some length from 1 to 4. Moreover, each Morse code representation of an English letter contains only dots and dashes. In this task, we will represent a dot with a “0” and a dash with a “1”.

Because there are 21+22+23+24=30 strings with length 1 to 4 containing only “0” and/or “1”, not all of them correspond to one of the 26 English letters. In particular, each string of “0” and/or “1” of length at most 4 translates into a distinct English letter, except the following four strings that do not correspond to any English alphabet: “0011”, “0101”, “1110”, and “1111”.

You will work with a string S, which is initially empty. For m times, either a dot or a dash will be appended to S, one at a time. Your task is to find and report, after each of these modifications to string S, the number of non-empty sequences of English letters that are represented with some substring of S in Morse code.

Since the answers can be incredibly tremendous, print them modulo 109+7.

Input
The first line contains an integer m (1≤m≤3000) — the number of modifications to S.

Each of the next m lines contains either a “0” (representing a dot) or a “1” (representing a dash), specifying which character should be appended to S.

Output
Print m lines, the i-th of which being the answer after the i-th modification to S.

Examples
inputCopy
3
1
1
1
outputCopy
1
3
7
inputCopy
5
1
0
1
0
1
outputCopy
1
4
10
22
43
inputCopy
9
1
1
0
0
0
1
1
0
1
outputCopy
1
3
10
24
51
109
213
421
833
Note
Let us consider the first sample after all characters have been appended to S, so S is “111”.

As you can see, “1”, “11”, and “111” all correspond to some distinct English letter. In fact, they are translated into a ‘T’, an ‘M’, and an ‘O’, respectively. All non-empty sequences of English letters that are represented with some substring of S in Morse code, therefore, are as follows.

“T” (translates into “1”)
“M” (translates into “11”)
“O” (translates into “111”)
“TT” (translates into “11”)
“TM” (translates into “111”)
“MT” (translates into “111”)
“TTT” (translates into “111”)
Although unnecessary for this task, a conversion table from English alphabets into Morse code can be found here.

题意:

给你一个01串,每给你一个就问你从开头到现在所有的子串能够构成多少种字符串,字符串可以由长度为1的01串,长度为2的01串3,4的01串构成,但是有4个长度为4的数字无法组成一个字符。注意:00和0是两码事。

题解:

对于每一个新进来的数字,我们只需要将上一个的答案和这个01串的所有新后缀加起来就好了,对于以当前加进来的数为后缀的情况,如果我们从前往后考虑,那么就是每次都删掉最前面的值,这样会很慢,不如从后往前考虑,每次都在上一个枚举到的后缀的字典树的末尾加上枚举到的开头,由于每个字符都是由1到4个数字组成,所以我们就考虑从当前枚举到的数字到这个位置+3的地方即可,在判断如果这个前缀的长度为4,是否是无效的字符,如果不是,那么就加到dp数组里,如果当前这个后缀在字典树里面没出现过,那么就将dp加到答案里。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=3e3+5;
int nxt[N*N][2],cnt;
int a[N],f[5];
ll dp[N],ans;
const ll mod=1e9+7;
int judge(int x)
{
    if(x==11||x==101||x==1110||x==1111)
        return 0;
    return 1;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        dp[i+1]=1;
        int rt=0;
        for(int j=i;j>=1;j--)
        {
            dp[j]=0;
            int num=min(4,i-j+1);
            if(num==4)
            {
                int sum=0;
                for(int k=j;k<j+4;k++)
                    sum=sum*10+a[k];
                if(judge(sum)==0)
                    num--;
            }
            for(int k=1;k<=num;k++)
                dp[j]=(dp[j]+dp[j+k])%mod;
            if(nxt[rt][a[j]])
            {
                rt=nxt[rt][a[j]];
                continue;
            }
            rt=nxt[rt][a[j]]=++cnt;
            ans=(ans+dp[j])%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/tianyizhicheng/article/details/88715665