HDU5510 - Bazinga(kmp+递归)
题目
题解
比较关键的一点:如果a包含b,b包含c,则a包含c。
所以可以定义solve(p)为返回第p个字符串之前不能被p包含的字符串的最大位置,在递归过程中找到取最大答案。
细节详见代码。这样递归处理复杂度为O(n)。
#include <bits/stdc++.h>
#define endl '\n'
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define FILE freopen(".//data_generator//in.txt","r",stdin),freopen("res.txt","w",stdout)
#define FI freopen(".//data_generator//in.txt","r",stdin)
#define FO freopen("res.txt","w",stdout)
#define pb push_back
#define mp make_pair
#define seteps(N) fixed << setprecision(N)
typedef long long ll;
using namespace std;
/*-----------------------------------------------------------------*/
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
#define INF 0x3f3f3f3f
const int N = 3e5 + 10;
const double eps = 1e-5;
int nt[N];
void getnext(char t[]) {
int i = 0, j = -1;
nt[i] = j;
while(t[i]) {
if(j == -1 || t[i] == t[j]) {
i++;
j++;
nt[i] = j;
} else {
j = nt[j];
}
}
}
bool search(char s[], char t[]) {
int i = 0;
int j = 0;
bool found = false;
while(s[i]) {
if(j == -1 || s[i] == t[j]) {
i++;
j++;
if(!t[j]) {
found = true;
break;
}
} else {
j = nt[j];
}
}
return found;
}
bool cover(char s1[], char s2[]) {
int l1 = strlen(s1), l2 = strlen(s2);
if(l1 < l2) return false;
getnext(s2);
return search(s1, s2);
}
char s[600][2000];
int ans;
int solve(int p) {
int nt = p - 1;
while(nt) {
if(cover(s[p], s[nt])) {
nt = solve(nt);
} else {
ans = max(ans, p);
return nt;
}
}
return 0;
}
int main() {
IOS;
int t;
int cas = 0;
cin >> t;
while(t--) {
ans = -1;
int n;
cin >> n;
for(int i = 1; i <= n; i++) {
cin >> s[i];
}
solve(n);
cout << "Case #" << ++cas << ": " << ans << endl;
}
}