Gym

▼魔方 西西 提交于 2020-08-10 18:34:18

ACM-ICPC Southeastern European Regional Programming Contest
Bucharest, Romania – Vinnytsya, Ukraine
October 22, 2016


Problem C Castle

Input File: C.in
Output File: standard output
Time Limit: 0.5 seconds (C/C++)
Memory Limit: 256 megabytes


K. has stumbled upon a weird game while playing on his computer. The game consists of an initial string S
of length N (1 ≤ N ≤ 1000) and an empty set T. The following events might occur during the game:
 a character is added at the end of S, thus increasing its length by 1
 the string S is added to the set T
 the game master inquires: “How many strings in T are suffixes of S?”. A suffix of S is a substring
which can start at any position in S, but must finish on the last position of S.
Because K. wants to go visit a famous castle near his hometown, you must help him deal with the game as
quickly as possible.








Input

The first line of the input contains two integers: N, the length of the initial string S and E, the number of
events (E ≤ 1200000).
The second line describes the string S; the string consists only of lowercase Roman alphabet (a-z).
The following E lines describe the events. Each of these lines contains an integer p, describing the event
type.
If p is 1, then it is followed by a character (a-z), which will be added at the end of S.
If p is 2, then the string S is added in T.
If p is 3, then you must respond to the query “How many strings in T are suffixes of the current S?”


Output

The output should consist of a line containing an integer for each type 3 event in the input, which represents
the answer to the query.
Note: T is a set, so it doesn't contain duplicates.
Note: Large input: for C scanf and printf recommended; for C++, add “cin.tie(NULL);
ios::sync_with_stdio(false);” before reading; for Java use BufferedReader and BufferedWriter.


Sample input      Sample output 

1 11                                                           1
a                                                                 2
2
1 b
1 a
2
2
1 c
1 a
3
1 b
1 a
3

Explanation

Initially S is “a”.
After the first event T becomes {“a”}.
After the second and third event S becomes
“aba”.
After the fourth event T becomes {“a”, “aba”}.
After the fifth event T becomes {“a”, “aba”}.
After the sixth and seventh event S becomes
“abaca”.
The result of the query is 1 (“a”).
After the ninth and tenth event S becomes
“abacaba”.
The result of the query is 2 (“a” and “aba”).












Source

Southeastern European Regional Programming Contest
Bucharest, Romania – Vinnytsya, Ukraine

Gym - 101164C


My Solution

题意:给出原串s,然后有3种操作,1、在s的末尾加上一个小写字母ch;2、把s的拷贝放入set;3、询问在set中的字符串是当前字符串s‘的后缀的个数。


KMP的拓展、next数组+dp

用构造出的最终串,跑出该字符串的next数组nxt[MAXN],并记录l[i] 为到操作i时字符串s的长度。

然后对于操作i = 1 ~ e,如果该操作是type2则标记f[i] = true, 并且对于每个i, u = l[i], ans = sum[u] = f[i] + sum[nxt[u]],然后如果是type三则把ans输出即可。

其中sum[u]表示到长度为u时的在set中的字符串是当时串的后缀的个数,这里应用KMP的next[i]表示最长的前缀==后缀来进行状态转移。

复杂度 O(n)


#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
typedef long long LL;
const int MAXN = 1.2e6 + 8;

string s;
int nxt[MAXN];
inline void get_nxt(const string& pattern)
{
    int n = pattern.size();
    for(int i = 1, j = 0; i < n; i++){
        j = i;
        while(j > 0){
            j = nxt[j];
            if(pattern[j] == pattern[i]){
                nxt[i + 1] = j + 1;
                break;
            }
        }
    }
}
int type[MAXN], l[MAXN], sum[MAXN];
bool f[MAXN];

int main()
{
    #ifdef LOCAL
    freopen("c.txt", "r", stdin);
    //freopen("c.out", "w", stdout);
    int T = 4;
    while(T--){
    #endif // LOCAL
    ios::sync_with_stdio(false); cin.tie(0);

    int n, e, i;
    char ch;
    cin >> n >> e;
    cin >> s;
    for(i = 0; i < e; i++){
        cin >> type[i];
        if(type[i] == 1){
            cin >> ch;
            s += ch;
            n++;
        }
        l[i] = n;
    }
    int len = s.size(), u, ans;
    get_nxt(s);
    for(i = 0; i < e; i++){
        if(type[i] == 2){
            f[l[i]] = true;
        }
        u = l[i];
        ans = sum[u] = f[u] + sum[nxt[u]];
        if(type[i] == 3) cout << ans << "\n";
    }

    #ifdef LOCAL
    cout << endl;
    }
    #endif // LOCAL
    return 0;
}


  Thank you!

                                                                                                                                             ------from ProLights
































易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!