ACM-ICPC Southeastern European Regional Programming Contest
Bucharest, Romania – Vinnytsya, Ukraine
October 22, 2016
Problem C Castle
Input File: C.inOutput 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 ofevents (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 representsthe 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
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
来源:oschina
链接:https://my.oschina.net/u/4258176/blog/4462787