rt,因为我太蒻了,所以看到这一题想不到正解,只知道要用 ACAM。所以直接糊了一个公式的 ACAM 上套 dp 的做法上去。
神必 dp 做法展示 ↓
#include<bits/stdc++.h>
using namespace std;
#define f(n,m,i) for(register int i(n);i<=m;++i)
#define nf(n,m,i) for(register int i(n);i>=m;--i)
#define dbug(x) cerr<<(#x)<<':'<<x<<' ';
#define ent cerr<<'\n';
#define ll long long
#define C cerr.tie(0),cout.tie(0),cin.tie(0)->sync_with_stdio(false);
constexpr int N(30005),mod(10007);
int n,m,dp[805][N],res(0);
string ps;
namespace AC{
int tot;
struct Node{
int s[2],cnt,fl,id;//子节点,匹配计数,fail指针,结束编号
void init(){ memset(s,0,sizeof s),cnt=fl=id=0;}
}t[N];
void ins(string c){
int x(0);
f(0,c.length()-1,i){
int &y(t[x].s[c[i]-'0']);
if (!y) y=++tot,t[y].init();
x=y;
}
t[x].id=1;
}
void bld(){
queue<int>q;
f(0,1,i) if (t[0].s[i]) q.push(t[0].s[i]);
while (!q.empty()){
int x(q.front());
q.pop();
f(0,1,i){
if (t[x].s[i]){
t[t[x].s[i]].id|=t[t[t[x].fl].s[i]].id;
t[t[x].s[i]].fl=t[t[x].fl].s[i];
q.push(t[x].s[i]);
}
else t[x].s[i]=t[t[x].fl].s[i];
}
}
}
}
using namespace AC;
int main(){ C
tot=0,t[0].init();
cin>>n,m=800;
f(1,n,i) cin>>ps,ins(ps);
bld();
dp[0][0]=1;
f(1,m,i)
f(0,tot,j)
f(0,1,k)
if(!t[t[j].s[k]].id)
dp[i][t[j].s[k]]|=dp[i-1][j];
f(0,tot,j) res|=dp[m][j];
if(res) cout<<"TAK\n";
else cout<<"NIE\n";
return 0;
}
但是用 ST(subtask)分治骗过那一个点的做法还是有点低能了,于是开始思考有没有方法能光明正大直接A掉此题。
不难发现考虑的 m 还是太小了,至少应该达到所有病毒片段的长度之和才行,但是这样的话会时空双响炮。然而,我还是抱着试一试的心态给 dp 数组滚了一下,时间就不管啦。
然后……过了???同时喜提一个最劣解
神必 AC dp 做法展示↓
#include<bits/stdc++.h>
using namespace std;
#define f(n,m,i) for(register int i(n);i<=m;++i)
#define nf(n,m,i) for(register int i(n);i>=m;--i)
#define dbug(x) cerr<<(#x)<<':'<<x<<' ';
#define ent cerr<<'\n';
#define ll long long
#define C cerr.tie(0),cout.tie(0),cin.tie(0)->sync_with_stdio(false);
constexpr int N(30005);
int n,m,dp[2][N],res(0);
string ps;
namespace AC{
int tot;
struct Node{
int s[2],cnt,fl,id;//子节点,匹配计数,fail指针,结束编号
void init(){ memset(s,0,sizeof s),cnt=fl=id=0;}
}t[N];
void ins(string c){
int x(0);
f(0,c.length()-1,i){
int &y(t[x].s[c[i]-'0']);
if (!y) y=++tot,t[y].init();
x=y;
}
t[x].id=1;
}
void bld(){
queue<int>q;
f(0,1,i) if (t[0].s[i]) q.push(t[0].s[i]);
while (!q.empty()){
int x(q.front());
q.pop();
f(0,1,i){
if (t[x].s[i]){
t[t[x].s[i]].id|=t[t[t[x].fl].s[i]].id;
t[t[x].s[i]].fl=t[t[x].fl].s[i];
q.push(t[x].s[i]);
}
else t[x].s[i]=t[t[x].fl].s[i];
}
}
}
}
using namespace AC;
int main(){ C
tot=0,t[0].init();
cin>>n;
f(1,n,i) cin>>ps,m+=ps.length(),ins(ps);
bld();
dp[0][0]=1;
f(1,m,i){
f(0,tot,j)
f(0,1,k)
if(!t[t[j].s[k]].id)
dp[i&1][t[j].s[k]]|=dp[~i&1][j];
f(0,tot,j) dp[~i&1][j]=0;
}
f(0,tot,j) res|=dp[m&1][j];
if(res) cout<<"TAK\n";
else cout<<"NIE\n";
return 0;
}
因此,建议加强本题数据卡掉这种神必做法