Fl,r,t
表示[l,r]区间的字符串是否能够用字符t代替
转移不是特别复杂,不过我还是拿记忆化搜索来写了
O(N3)
状态,每个状态
O(N)
转移,总时间代价
O(N4)
#include <bits/stdc++.h>
#define N 305
using namespace std;
int g[5][5][5];
int dp[N][N][5],vis[N][N][5],n[5],m,a[N],tot;
char s[N];
int get(char x) {
if (x=='W') return 1;
if (x=='I') return 2;
if (x=='N') return 3;
if (x=='G') return 4;
return 0;
}
void init() {
scanf("%d%d%d%d",&n[1],&n[2],&n[3],&n[4]);
for (int _=1;_<=4;_++)
for (int i=1;i<=n[_];i++) {
scanf("%s",s+1);
int x = get(s[1]), y = get(s[2]);
g[x][y][_] = 1;
}
}
int F(int l,int r,int t) {
if (l==r) return a[l]==t;
if (vis[l][r][t]) return dp[l][r][t];
int ret = 0;
for (int i=l;i<r;i++)
for (int x=1;x<=4;x++)
for (int y=1;y<=4;y++) if (g[x][y][t])
F(l,i,x)&&F(i+1,r,y) ? ret = 1 :0;
vis[l][r][t] = 1; dp[l][r][t] = ret;
return ret;
}
void solve() {
scanf("%s",s+1); m = strlen(s+1);
for (int i=1;i<=m;i++) a[i] = get(s[i]);
if (F(1,m,1)) putchar('W'), tot++;
if (F(1,m,2)) putchar('I'), tot++;
if (F(1,m,3)) putchar('N'), tot++;
if (F(1,m,4)) putchar('G'), tot++;
if (!tot) printf("The name is wrong!");
putchar('\n');
}
int main() {
#ifndef ONLINE_JUDGE
freopen("tmp.in","r",stdin);
#endif
init();
solve();
return 0;
}